zl程序教程

您现在的位置是:首页 >  其他

当前栏目

如何高效生成趋势有序的全局唯一ID

趋势 如何 生成 高效 ID 全局 唯一 有序
2023-09-14 09:00:01 时间

所有的业务系统,都有生成ID的需求,如订单id,商品id等

这个ID会是数据库中的唯一主键,在它上面会建立聚集索引

ID生成的核心需求:

  (1)全局唯一

  (2)趋势有序

1.使用数据库的 auto_increment 来生成全局唯一递增ID

优点:

(1)简单

(2)能够保证唯一性

(3)能够保证递增性

(4)步长固定

缺点:

(1)可用性难以保证:数据库架构是一主多从+读写分离,生成自增ID是写请求,主库挂了就玩不转了

(2)扩展性差,性能有上限:因为写入是单点,数据库主库的写性能决定ID的生成性能上限,并且难以扩展

改进方法:

(1)增加主库,避免写入单点

(2)数据水平切分,保证各主库生成的ID不重复

改进后保证了可用性,但缺点是:

(1)丧失了ID生成的“绝对递增性”

(2)数据库的写压力依然很大,每次生成ID都要访问数据库

2.单点批量ID生成服务

每次生成ID都访问了数据库,使用批量的方式降低数据库写压力

数据库中只存储当前ID的最大值,

如果当前为0,

ID生成服务每次批量拉取6个ID,服务访问数据库,将当前ID的最大值修改为5,应用访问ID生成服务索要ID,ID生成服务不需要每次访问数据库,就能依次派发0,1,2,3,4,5

当ID发完后,再将ID的最大值修改为11,就能再次派发6,7,8,9,10,11

优点

(1)保证了ID生成的绝对递增有序

(2)大大的降低了数据库的压力

缺点

(1)服务仍然是单点

(2)如果服务挂了,服务重启起来之后,继续生成ID可能会不连续,中间出现空洞

(3)虽然每秒可以生成几万几十万个ID,但还是有性能上限,无法进行水平扩展

改进方法

单点服务高可用优化方案是“备用服务”

对外提供的服务是主服务,备用服务时刻处于备用状态,当主服务挂了的时候备用服务顶上。

这个切换的过程对调用方是透明的,可以自动完成,常用的技术是vip+keepalived

3.uuid

string ID =GenUUID();

优点

(1)本地生成ID,不需要进行远程调用,时延低

(2)扩展性好,基本可以认为没有性能上限

缺点

(1)无法保证趋势递增

(2)uuid过长,往往用字符串表示,作为主键建立索引查询效率低

优化方案为“转化为两个uint64整数存储”或者“折半存储”(折半后不能保证唯一性)

4.取当前毫秒数

uint64 ID = GenTimeMS();

优点

(1)本地生成ID,不需要进行远程调用,时延低

(2)生成的ID趋势递增

(3)生成的ID是整数,建立索引后查询效率高

缺点

(1)如果并发量超过1000,会生成重复的ID

5.类snowflake算法

snowflake是twitter开源的分布式ID生成算法

核心思想是:一个long型的ID,使用其中41bit作为毫秒数,10bit作为机器编号,12bit作为毫秒内序列号