IM系统的分布式id生成器

1.背景

在复杂分布式系统中,往往需要对大量的数据进行唯一标识。一般情况下,我们用的都是数据库的自增主键id,但是当数据量大了之后,需要进行分库分表,每个表维护自己的自增id,无法做到唯一。这时候就需要一个全局的id发号器,生成一个唯一标识。看看我们对id生成一般有以下三个期望:

全局唯一:最基本的要求,标识唯一的记录

递增

  • 单调递增:有些场景,需要根据生成的id进行排序,需要严格递增,比如IM消息,不能乱序,靠id递增。微信为此做了个单调递增的发号服务,阅读算法篇,容灾篇。

  • 趋势递增:在分布式场景下,保证本地单调递增,全局趋势递增。是考虑实现复杂度和高性能的一个取舍后的结果。为什么需要趋势递增呢?因为我们数据库的索引比如Innodb是顺序的,如果新增的数据不递增,不是在末尾加入,而是插入索引的中间。会造成页分裂问题

信息安全:如果我们的分布式id有一定的新增规律,比如连续增加,就能被竞争对手猜出,业务的增长情况。比如每天产生了多少订单,在一些特殊的场景下,id的生成需要做到无规律。

页分裂问题可能会导致数据存储结构的调整和重新平衡,以及对索引的维护和更新。这种操作可能会影响数据库的性能,特别是在频繁进行插入操作的情况下。因此,在数据库设计和性能优化中,需要考虑如何有效地管理页分裂问题,以减少对数据库性能的影响。

趋势递增和单调递增都可以有助于减少页分裂问题。当索引键按照递增顺序排列时,无论是趋势递增还是单调递增,新数据通常会被追加到已有数据的末尾,而不会插入到已有数据中间。这种方式可以避免数据页频繁地进行分裂操作,因为新数据的插入不会导致现有数据页的重组或重新平衡。

2.递增类型

2.1 全局递增

消息在整个IM系统都是唯一且递增的。一般对于单表来说主键就自然保证了递增。但是如果消息量大了,省不了分库分表,分库分表后的消息递增,通常采用分布式id。但是分布式id通常保证的是趋势递增,而不是单调递增

比如说,雪花id就不适用于IM这种严格时序性的系统。事实上,严格的单调递增,意味着严重的单点竞争问题。对于一个都需要分库分表的系统,是很难实现这样的方案的。

2.2 会话级别递增

上面也说到,全局的单调递增,意味着严重的单点竞争。话说回来,我们为啥需要递增呢?不就是为了消息的顺序性展示吗?只需要保证单个群组内的消息id是有序的且唯一的,就足够了。QQ就是这样的架构。

那么如何保证会话级别的递增呢?一个简单的做法分库分表以会话id分表。这样相同的会话必定在同一张表,又重新用回了主键自增。但是,这种方案很难支持之后的扩容,比如4扩8。所以一般分表就不用主键自增了,都是用分布式id。

用分布式id保证会话级别的单调递增:单调递增,同时意味着单点问题。两者是不可两全的。分布式id之所以没有单点问题,所以大多都是趋势递增。这里面涉及的可用性,以及单调递增这种一致性的取舍。非常有意思。最终实现的效果,类似mysql的主从,单点的mysql用于自增id,以及主从保证高可用的切换。实现参考:微信序列号生成器架构设计。

2.3 收信箱递增

会话级别的递增,更多的适用于读扩散的场景。所有人拉取消息列表的时候,都去会话的消息表拉取。

收信箱的递增,适用于写扩散的场景。所有人都有自己的一个收信箱,维护自己的时间线即可。

收信箱的时间线的单调递增和uid相关。实现的方式和上面都一样,一个是以会话为key,一个是以uid为key。实现参考:微信序列号生成器架构设计

微信就是典型的写扩散场景,所以他的群聊最多只能500人。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/505349.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于synchronized介绍

synchronized的特性 1. 乐观锁/悲观锁自适应,开始时是乐观锁,如果锁冲突频繁,就转换为悲观锁 2.轻量级/重量级锁自适应 开始是轻量级锁实现,如果锁被持有的时间较长,就转换成重量级锁 3.自旋/挂起等待锁自适应 4.不是读写锁 5.非公平锁 6,可重入锁 synchronized的使用 1&#…

yolov8添加注意力机制模块-ShuffleAttention

修改 原本打算把ShuffleAttention模块先写进conv.py文件中,然后在引入tasks.py文件中。但是不知道咋回事,在tasks.py文件中引入报红。所以干脆直接把ShuffleAttention模块写进了tasks.py文件中。 from torch.nn import init from torch.nn.parameter i…

【黑马程序员】5、TypeScript类型声明文件_黑马程序员前端TypeScript教程,TypeScript零基础入门到实战全套教程

课程地址:【黑马程序员前端TypeScript教程,TypeScript零基础入门到实战全套教程】 https://www.bilibili.com/video/BV14Z4y1u7pi/?share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 目录 5、TypeScript类型声明文件 5.1 TS中的…

一文掌握大模型提示词技巧:从战略到战术

作者:明明如月学长, CSDN 博客专家,大厂高级 Java 工程师,《性能优化方法论》作者、《解锁大厂思维:剖析《阿里巴巴Java开发手册》》、《再学经典:《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

Python中网络请求超时的原因及解决方案

在进行网络数据爬取过程中,网络请求超时是一个令人头疼的问题。尤其在Python中,我们常常需要应对各种网络爬虫、API调用或其他网络操作,而网络请求超时的原因千奇百怪。在本篇文章中,我们将深入了解网络请求超时的可能原因&#x…

C++:纯虚函数及抽象类

1.纯虚函数 在虚函数的声明后加“0” ,表示当前虚函数无需定义 eg: class Shape //图形类 { public:virtual double circum()const 0;//周长,纯虚函数virtual double area()const 0; //面积,纯虚函数virtual void show()const; //输出,虚函数 }; 2.抽…

SQL窗口函数, 测试题

第一题 create table user_score (logday date, -- 考试时间 userid VARCHAR(20), -- 考试用户 score int); -- 考试成绩Insert into user_score values (2019-10-20,11111,85) ,(2019-10-20,22222,83) ,(2019-10-20,33333,86) ,(2019-10-21,11111,87) ,(2019-10-2…

贪心 Leetcode 376 摆动序列

摆动序列 Leetcode 376 学习记录自代码随想录 如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。 例如&#…

【数据结构】知识点一:线性表之顺序表

内容导航 一、什么是线性表?二、什么是顺序表?1、顺序表的概念2、顺序表的结构a. 静态顺序表:使用定长数组存储元素。b. 动态顺序表:使用动态开辟的数组存储。 三、顺序表的接口实现精讲1.接口一:打印数据2.接口二&…

算法 -【最小路径和】

最小路径和 题目示例1示例2 分析代码 题目 给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 说明:每次只能向下或者向右移动一步。 示例1 输入:grid [[1,3,1],[1,5,1…

Ethernet/IP转Modbus TCP网关

产品功能 1 YC-EIP-TCP工业级EtherNet/IP 网关 2 Modbus TCP 转 EtherNet/IP 3支持ModBus主从站 4 即插即用 无需编程 轻松组态 ,即实现数据交互 5导轨安装 支持提供EDS文件 6 EtherNET/IP与ModBus互转数据透明传输可接入PLC组态 支持CodeSys/支持欧姆龙PLC 支持罗克韦尔(AB) 典…

FastAPI 的 quickstart

从这一章往后我们就正式开始学习 FastAPI 了 代码 FastAPI 环境安装 python 环境安装 根据要求至少需要 python 3.8及其以上,可以去 python 官网 自行下载安装, 本文中我们用 python 3.11 FastAPI 环境安装 pip install fastapi pip install "uvicorn[sta…