分布式id生成器方案详细介绍(百度分布式id生成器)
cac55 2024-10-20 04:22 11 浏览 0 评论
问题描述
在物联网场景的解决方案中,通常需要将设备的信息转换为一个业务事件进行输出。在生成/升级事件的过程往往需要多次的数据库操作,且伴随着异步的逻辑。依靠数据库的自增id作为事件的id容易造成脏数据且会占用大量的数据库资源,所以需要系统内置一个轻量级的id生成器。
常见解决方案
UUID
UUID(universally unique identifier)是基于时间生成的128位随机标识符,算法保证了UUID重复的可能性接近于0,且UUID的生成不依赖中心注册单元,完全是分布式生成的。JAVA自带了生成UUID的类库。
public static void main(String[] args) {
String uuid = UUID.randomUUID().toString().replaceAll("-","");
System.out.println(uuid);
}
优点:
生成足够简单,本地生成无网络消耗,具有唯一性
缺点:
无序的字符串,不具备趋势自增特性
没有具体的业务含义
长度过长16 字节128位,字符串36位,很难作为主键保存。
数据库自增ID
基于数据库的auto_increment自增ID完全可以充当分布式ID,具体实现:需要一个单独的MySQL实例用来生成ID,建表结构如下:
CREATE TABLE SEQUENCE_ID (
id bigint(20) unsigned NOT NULL auto_increment,
tag char(10) NOT NULL default '',
PRIMARY KEY (id),
) ENGINE=INNODB;
当需要一个ID的时候,向表中插入一条记录返回主键ID.
insert into SEQUENCE_ID(value) VALUES ('tag');
数据库集群自增ID
由于单个数据库有可能造成单点故障,所以数据库自增还可以基于数据库集群来提供。可以避免因为单点造成的不可用,ID重复的问题可以通过给每个数据库设置不同的起始id和步长进行控制。
MySQL_1 配置:
set @@auto_increment_offset = 1; -- 起始值
set @@auto_increment_increment = 2; -- 步长
MySQL_2 配置:
set @@auto_increment_offset = 2; -- 起始值
set @@auto_increment_increment = 2; -- 步长
优点:
实现简单,ID单调自增,数值类型查询速度快
缺点:
无法支持高并发场景,单机模式有不可用风险,集群模式后期无法扩容。
号段模式
号段模式可以理解为从数据库批量的获取自增ID,每次从数据库取出一个号段范围,例如 (1,1000] 代表1000个ID,具体的业务服务将本号段,生成1~1000的自增ID并加载到内存。表结构如下:
CREATE TABLE SEGAMENT_ID (
id int(10) NOT NULL,
max_id bigint(20) NOT NULL COMMENT '当前最大id',
step int(20) NOT NULL COMMENT '号段的步长',
tag varchar(8) NOT NULL COMMENT '业务标识',
version int(20) NOT NULL COMMENT '是一个乐观锁,每次都更新version,保证并发时数据的正确性',
PRIMARY KEY (`id`)
)
表里插入初始化的数据,确定步长和id初始值。
insert into SEGAMENT_ID (`max_id`,`step`,`tag`,`version`) values(1,1000,'tag',1);
将(1,1000]放到内存里供系统使用。
等这批号段ID用完,再次向数据库申请新号段,对max_id字段做一次update操作,max_id= max_id + step,update成功则说明新号段获取成功,新的号段范围是(max_id ,max_id +step]。
update SEGAMENT_ID set max_id = #{max_id+step}, version = version + 1 where version = # {version} and tag ='tag'
优点:
高并发,不会占用大量数据库性能。
缺点:
当吞吐量上去后,依旧存在单点故障问题。
redis自增
基于用redis的 incr命令实现ID的原子性自增,也可视实现uid快速生成。
127.0.0.1:6379> set seq_id 1 // 初始化自增ID为1
OK
127.0.0.1:6379> incr seq_id // 增加1,并返回递增后的数值
(integer) 2
优点:
支持较大的吞吐量,不会占用大量数据库性能。
缺点:
高并发下占用较大的网络IO资源。id完全自增,有信息安全问题。
snowflake算法
Twitter公司开源的id生成算法,基于机器的时钟服务和节点信息生成id。
Snowflake生成的是Long类型的ID,共占64个比特。
其中:正数位(占1比特)+ 时间戳(占41比特)+ 机器ID(占5比特)+ 数据中心(占5比特)+ 自增值(占12比特)。
第一个bit位(1bit):Java中long的最高位是符号位代表正负,正数是0,负数是1,一般生成ID都为正数,所以默认为0。
时间戳部分(41bit):毫秒级的时间,不建议存当前时间戳,而是用(当前时间戳 - 固定开始时间戳)的差值,可以使产生的ID从更小的值开始;41位的时间戳可以使用69年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年
工作机器id(10bit):也被叫做workId,这个可以灵活配置,机房或者机器号组合都可以。
序列号部分(12bit),自增值支持同一毫秒内同一个节点可以生成4096个ID。
在使用中,可以根据实际情况对每个部分的占比进行调整。
优点
没有网络IO开销,ID不连续,没有安全问题。
缺点
依赖时钟服务,当时间回调后会出现id重复。
混合使用
以上5种生成方案都有不同的缺点,在实际使用过程中各厂倾向于混合使用几种策略来满足自身的需求。
uid-generator
百度的uid-generator基于snowflake算法。解决了时钟回拨和瞬时高并发的问题。
uid-generator默认workNodeId持久化在数据库中,但也提供了重新实现workNodeId的接口。当时间回拨后,会自动生成新的nodeId,保证uid整体的不重复。
RingBuffer保存了当前可用的所有id序列,tail和cursor表示最新生成id和最新使用id,环状结构保证了序列的填充不用非得在正数时刻进行。由于不依赖时间服务,可以向未来借用时间生成id。解决了瞬时高并发的问题。
Leaf
美团团队根据业务场景提出了基于号段思想的 Leaf-Segment 方案和基于 Snowflake 的 Leaf-Snowflake 方案。出现两种方案的原因是Leaf-Segment并没有满足安全属性要求,容易被猜测。无法用在对外开放的场景(如订单)。Leaf-Snowflake 通过文件系统缓存降低了对 ZooKeeper 的依赖,同时通过对时间的比对和警报来应对 Snowflake 的时间回拨问题。
Seqsvr
微信并没有全局id,但他会为每个用户创建一组id,单个用户的id是顺序且唯一的。由于单个用户的吞吐量有限,该方案没有依赖时间服务,而是基于自增数和号段解决。
场景分析
基于部署成本和运维成本的考虑,事件中心被设计成既可以被集成部署,也可以独立部署的模式。所以在实际的环境中,往往会存在多个事件中心的实例。
这些情况对id生成器提出额外的要求:id的生成不能依赖单一中心组件,比如停车解决方案的数据库挂了,不能影响排水解决方案的id生成。且一个环境多个实例生成的id不能重复。
此外,应用需要在专有云,共有云等多种环境中部署。id生成器不能依赖时间服务。
最后,考虑到物联网的场景下,往往会产生事件风暴。所以id的生成还必须能够支持瞬时高并发。
综上现有的方案并不能100%的满足我们的需求,需要对其进行改造。
最终方案
id结构
基于以上的需求,我们采用snowflak算法作为基础进行了优化。我们依旧把64位分成4部分,其中:1bit符号,30bit时间偏移量,20bit机器id,13bit序列。
30bit的时间偏移量我们使用秒作为单位,可以支持34年使用。
20bit的机器id,支持每秒近50w台机器。
13bit的序列,可以支持8000qps的请求,对于单个解决方案来说足够了。
时间回拨
时间回拨通常有几个思路:
1. 缓存每毫秒的seq记录,当回拨时间时,使用之前没有用的seq创建新id,缺点是有可能会不够用。
2. 等待当前时间到lastTime,缺点是当回拨时间过长时,可用性无法保证。
3. 不再持续获取服务器最新时间,只在启动时获取一次时间,之后每个节点采取自增的方式维护自己的lastTime。当发现时间回拨时,更新一次nodeId。缺点是id中的“时间戳delta”并不代表实际生成的时间的偏移量。
经过评估第三种实现可以比较好的避免时间回拨问题。我们将nodeId持久化保存。每当机器启动时,或发现时间回拨时,在数据库里注册一个新的node记录,将新的id作为nodeId使用.
CREATE TABLE csa_work_node(
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`host_name` VARCHAR(64) NOT NULL COMMENT 'host name',
`port` VARCHAR(64) NULL COMMENT 'port',
`type` INT NOT NULL COMMENT 'node type: ACTUAL or CONTAINER',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'modified time',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP COMMENT 'created time',
`is_deleted` bigint unsigned NOT NULL DEFAULT 0 COMMENT '是否删除0:未删除,1:删除',
PRIMARY KEY(`id`)
) DEFAULT CHARACTER SET=utf8mb4 COMMENT='WorkNodeId';
由于需要持久化nodeId的信息,就需要考虑单点故障的问题。在这里我们将nodeId分为两部分,5bit的groupId和15bit的workId。“groupId”是由事件中心颁发给各解决方案的的分段标识,用以区分各解决方案产生的事件,“workId”用来标识每个id生成器实例的机器。
每个解决方案维护自己的workId,互相之间不影响。最终的nodeId为groupId+workId%32768。这样可以保证每秒2^15次的重启和时间回拨。
瞬时高并发
由于在解决时间回拨问题时,我们去掉了对时间服务的依赖,由每个实例维护自己的lastTime,所以具备了借用未来时间生成id的可能,在参考了uid-genenrator的实现后,我们这里直接使用uid-generator作为seqId的生成逻辑。
总结
通过上诉的设计,我们实现了不依赖时间服务的id生成器。且在多个实例同时存在的情况下,可以做到互相之间不影响,生成的id不重复。
- 上一篇:PL/SQL中的序列:自动递增主键生成器
- 下一篇:通过代码看懂设计模式——单例模式
相关推荐
- MIRIX重塑AI记忆:超Gemini 410%,节省99.9%内存,APP同步上线
-
MIRIX,一个由UCSD和NYU团队主导的新系统,正在重新定义AI的记忆格局。在过去的十年里,我们见证了大型语言模型席卷全球,从写作助手到代码生成器,无所不能。然而,即使最强大的模型依...
- 硬盘坏了怎么把数据弄出来对比10种硬盘数据恢复软件
-
机械硬盘或固态硬盘损坏导致数据丢失时,应立即停止对硬盘的读写操作,并根据损坏类型选择逻辑层恢复工具或专业物理恢复服务。紧急处置措施立即停止通电使用:发现硬盘异响、无法识别或数据异常时,需立即断开连接,...
- 蓝宝石B850A WIFI主板新玩法:内存小参调节体验
-
蓝宝石前段时间发布了一款性价比极高的主板:NITRO氮动B850AWIFI主板。这款主板的售价只要1349元,相比普遍1500元以上的B850主板,确实极具竞争力。虽然价格实惠,蓝宝石NITR...
- 内存卡损坏读不出怎么修复?这5个数据恢复工具汇总,3秒挽回!
-
在数字化生活的浪潮中,内存卡凭借小巧便携与大容量存储的特性,成为相机、手机、行车记录仪等设备存储数据的得力助手,承载着无数珍贵回忆与重要文件。然而,当内存卡突然损坏无法读取,无论是误删、格式化、病毒入...
- 内存卡修复不再难,2025年必学的6款软件工具
-
内存卡出现问题时,通常是因为文件系统损坏、物理损坏或病毒感染。通过专业的修复工具,我们可以尝试恢复数据并修复内存卡。内存卡修复利器:万兴恢复专家万兴恢复专家是一款功能强大的数据恢复软件,支持多种设备和...
- 有5款内存卡修复工具汇总,内存卡数据轻松找回!
-
在如今的数字时代,内存卡作为不可或缺的存储介质,广泛应用于相机、手机、行车记录仪等各类设备中,承载着我们珍贵的照片、视频以及重要文件。然而,数据丢失的风险却如影随形,误删、格式化、病毒入侵、硬件故障等...
- 揭秘:如何通过多种方式精准查询内存条型号及规避风险?
-
以下是内存条型号查询的常用方法及注意事项,综合了物理查看、软件检测、编码解析等多种方式:一、物理标签查看法1.拆机查看标签打开电脑主机/笔记本后盖找到内存条,观察标签上的型号标识。例如内存标签通常标...
- 内存卡数据恢复5个工具汇总推荐,轻松找回珍贵记忆!
-
在这个数字化时代,内存卡作为我们存储珍贵照片、重要文件的常用载体,广泛应用于手机、相机、平板电脑等设备。但数据丢失的意外却常常不期而至,误删除、格式化、病毒攻击,甚至内存卡的物理损坏,都可能让辛苦保存...
- 电脑内存智能监控清理,优化性能的实用软件
-
软件介绍Memorycleaner是一款内存清理软件。功能很强,效果很不错。Memorycleaner会在内存用量超出80%时,自动执行“裁剪进程工作集”“清理系统缓存”以及“用全部可能的方法清理...
- TechPowerUp MemTest64:内存稳定性测试利器
-
TechPowerUpMemTest64:内存稳定性测试利器一、软件简介TechPowerUpMemTest64,由知名硬件信息工具GPU-Z的出品公司TechPowerUp发布,是一款专为64位...
- 微软推出AI恶意软件检测智能体Project Ire,精确度高达98%
-
IT之家8月6日消息,当地时间周二,微软宣布推出可自主分析恶意软件的AI检测系统原型——ProjectIre。该项目由微软研究院、Defender研究团队及Discovery&a...
- 农村老木匠常用的20种老工具,手艺人靠它养活一家人,你认识几种
-
生活中的手艺老匠人是非常受到尊敬和崇拜的,特别是在农村曾经的老匠人都是家里的“座上宾”。对于民间传统的手艺人,有一种说法就是传统的八大匠:木匠、泥匠、篾匠、铁匠、船匠、石匠、油匠和剃头匠。木匠的祖始爷...
- 恶意木马新变种伪装成聊天工具诱人点击
-
国家计算机病毒应急处理中心通过对互联网监测发现,近期出现一种恶意木马程序变种Trojan_FakeQQ.CTU。该变种通过伪装成即时聊天工具,诱使计算机用户点击运行。该变种运行后,将其自身复制到受感染...
- 学习网络安全 这些工具你知道吗?
-
工欲善其事必先利其器,在新入门网络安全的小伙伴而言。这些工具你必须要有所了解。本文我们简单说说这些网络安全工具吧!Web安全类web类工具主要是通过各种扫描工具,发现web站点存在的各种漏洞...
- 5分钟盗走你的隐私照片,这个全球性漏洞到底有多可怕?
-
这个时代,大家对电脑出现漏洞,可能已经习以为常。但如果机哥告诉大家,这个漏洞能够在5分钟内,破解并盗取你所有加密文件,而且还无法通过软件和补丁修复...这可就有点吓人啦。事情是酱婶的。来自荷兰埃因...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- 如何绘制折线图 (52)
- javaabstract (48)
- 新浪微博头像 (53)
- grub4dos (66)
- s扫描器 (51)
- httpfile dll (48)
- ps实例教程 (55)
- taskmgr (51)
- s spline (61)
- vnc远程控制 (47)
- 数据丢失 (47)
- wbem (57)
- flac文件 (72)
- 网页制作基础教程 (53)
- 镜像文件刻录 (61)
- ug5 0软件免费下载 (78)
- debian下载 (53)
- ubuntu10 04 (60)
- web qq登录 (59)
- 笔记本变成无线路由 (52)
- flash player 11 4 (50)
- 右键菜单清理 (78)
- cuteftp 注册码 (57)
- ospf协议 (53)
- ms17 010 下载 (60)