admin管理员组文章数量:1444613
架构师究竟要不要懂细节?分布式ID生成的6种方法(第45讲)
《架构师之路:架构设计中的100个知识点》
45.分布式ID生成
几乎所有的业务系统,都有生成一个唯一记录标识的需求,例如:消息ID,订单ID,帖子ID...
这个ID,在数据库中往往用作主键,且有排序与分页的查询需求。这也是分布式ID生成算法的两大核心需求:
1. 全局唯一;
2. 趋势递增;
如何高效生成趋势有序的全局唯一ID,是每一个工程师都会遇到的问题。
方法一:数据库auto-inc-id法
借助数据库的auto_increment来生成全局唯一递增ID。
优点:
1. 简单,使用数据库已有的功能;
2. 能够保证唯一性;
3. 能够保证递增性;
4. 步长固定;
不足:
1. 可用性难以保证,需要依赖数据库的高可用;
2. 扩展性差,性能有上限,数据库主库的写性能决定ID的生成性能上限;
改进方法:
1. 冗余主库,避免写入单点;
2. 数据水平切分,保证各主库生成的ID不重复;
改进后,数据库的写压力依然很大,每次生成ID都要访问数据库。为了解决这个问题,引出了第二个常见的方案。
方法二:批量ID生成服务
数据库写压力大,是因为每次生成ID都访问了数据库,可以使用批量的方式降低数据库写压力。
ID生成服务假设每次批量拉取6个ID,服务访问数据库,将当前ID的最大值修改为5,这样应用访问ID生成服务索要ID,ID生成服务不需要每次访问数据库,就能依次派发0,1,2,3,4,5这些ID了。
当ID发完后,再将ID的最大值修改为11,就能再次派发6,7,8,9,10,11这些ID了,于是数据库的压力就降低到原来的1/6。
优点:
1. 保证了ID生成的绝对递增有序;
2. 大大的降低了数据库的压力,ID生成可以做到每秒生成几万几十万个;
同时,服务也可以做集群化,只是稍微要注意数据一致性问题,具体CAS优化方案在《巧用CAS实现分布式ID生成器!(43)》中有详细介绍,不再展开。
方法三:uuid/guid法
不管是通过数据库,还是通过服务来生成ID,业务方都需要进行一次远程调用,比较耗时。有没有一种本地生成ID的方法,即高性能,又时延低呢?
uuid是一种常见的方案:
代码语言:javascript代码运行次数:0运行复制string ID =GenUUID();
优点:
1. 本地生成ID,不需要进行远程调用,时延低;
2. 扩展性好,基本可以认为没有性能上限;
不足:
1. 无法保证趋势递增
2. uuid过长,往往用字符串表示,作为主键建立索引查询效率低,常见优化方案为“转化为两个uint64整数存储”。
方法四:取当前毫秒数
uuid是一个本地算法,生成性能高,但无法保证趋势递增,且作为字符串ID检索效率低,有没有一种能保证递增的本地算法呢?
取当前毫秒数是一种常见方案:
代码语言:javascript代码运行次数:0运行复制uint64 ID = GenTimeMS();
优点:
1. 本地生成ID,不需要进行远程调用,时延低;
2. 生成的ID趋势递增;
3. 生成的ID是整数,建立索引后查询效率高;
缺点:如果并发量超过1000,会生成重复的ID。
当然,使用微秒可以降低冲突概率,但每秒最多只能生成1000000个ID,再多的话就一定会冲突了,所以使用微秒并不从根本上解决问题。
方法五:类snowflake算法
snowflake是twitter开源的分布式ID生成算法,其核心思想为,一个long型的ID:
1. 41bit作为毫秒数;
2. 10bit作为机器(服务)编号;
3. 12bit作为毫秒内序列号;
算法单机每秒内理论上最多可以生成1000*(2^12),也就是400W的ID,1024台机器(服务)每秒能生活40Y的ID,完全能满足业务的需求。
借鉴snowflake的思想,结合公司的业务逻辑和并发量,可以实现自己的分布式ID生成算法。
举例,假设某公司ID生成的需求如下:
1. 单机高峰并发量小于1W,预计未来10年单机高峰并发量小于10W;
2. 有2个机房,预计未来10年机房数量小于4个;
3. 每个机房机器数小于100台;
4. 目前有5个业务线有ID生成需求,预计未来业务线数量小于10个;
5. …
我们应该怎么来设计公司独特的ID生成算法呢?
其一,毫秒位数考虑。
假设系统至少运行10年,那至少需要10年*365天*24小时*3600秒*1000毫秒=320*10^9,差不多预留39bit给毫秒数。
其二,1毫秒内序列号考虑。
每秒的单机高峰并发量小于10W,即平均每毫秒的单机高峰并发量小于100,差不多预留7bit给每毫秒内序列号。
其三,机房数少于4个,预留2bit给机房标识。
其四,每个机房机器小于100台,预留7bit给每个机房内的服务器标识。
其五,业务线小于10个,预留4bit给业务线标识。
这样设计的64bit标识,可以保证:
1. 每个业务线、每个机房、每个机器生成的ID都是不同的;
2. 同一个机器,每个毫秒内生成的ID都是不同的;
3. 同一个机器,同一个毫秒内,以序列号区区分保证生成的ID是不同的;
4. 将毫秒数放在最高位,保证生成的ID是趋势递增的;
以上,希望大家有收获。
知其然,知其所以然。
思路比结论更重要。
扩展阅读:
==全文完==
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2025-03-20,如有侵权请联系 cloudcommunity@tencent 删除服务架构师算法数据库分布式本文标签: 架构师究竟要不要懂细节分布式ID生成的6种方法(第45讲)
版权声明:本文标题:架构师究竟要不要懂细节?分布式ID生成的6种方法(第45讲) 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/biancheng/1748198724a2824805.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论