分布式ID生成策略

分布式环境下的ID生成策略

考虑的维度

在选择ID生成策略时,通常要根据不同的业务场景考虑下面几个维度:

全局唯一性:ID是否需要全局唯一

高并发下的高可用性:ID的生成需要支持高并发,保证高可用性

趋势递增:ID生成一般要趋势递增(不一定要严格递增),这样作为数据库的主键时可增加性能

信息安全:ID中不要泄露用户敏感信息,如手机号、生日等比较明显的信息

4种策略

UUID:java的UUID.randomUUID()

数据库自增ID:

利用DB自身的自增能力,比如mysql中,auto_increment_increment=3表示每次ID增加3,auto_increment_offset=1表示ID从1开始增加;

在数据库集群中,如果没有一个中心化的ID生成器,那么就需要依赖各个数据库节点自行生成ID了,这个时候一个办法就是在各个节点中设置相同的auto_increment_increment,设置不同的auto_increment_offset。比如集群中A、B、C共3个db节点,3个节点的increment都设置成3,offset分别设置为1、2、3,那么A生成的ID序列为1,4,7…,B为2,5,8…,C为3,6,9…,这样可以保证ID的全局唯一和趋势递增,但是当我们需要扩容增加一个新的节点D时,要保证ID的全局唯一可能没那么容易。

如果数据库集群中有一个专门用来分配ID的服务,每次需要生成ID时,db节点来询问这个ID生成服务,这样就没有上面扩容的瓶颈了。但是如果每一个ID的生成都需要询问的话,这个中心化的ID生成服务可能会很快成为瓶颈,可以每次给一个db节点分配多个ID,比如给节点A分配1~1000,给B分配1001~2000,给C分配2001~3000,每个节点自己递增地生成分配到的1000个ID,当节点A、B、C的ID都消耗殆尽后,再向ID生成服务索取若干个ID

snowflake:twitter开源算法,服务器时间戳+集群ID+服务器ID+自增序列

redis:利用incr命令不断加1

优缺点对比

策略 优点 缺点 格式
UUID 实现简单,无网络消耗 可读性差;无序,作为主键查询慢 32位字符串
数据库自增ID 代码简单,递增 DB单点故障,扩展性瓶颈
snowflake 无网络消耗,低位趋势递增 依赖服务器时间,有可能时钟漂移 18位整数
redis 无单点故障,性能由于DB,递增 有网络消耗,Redis集群维护成本 12位整数