分布式ID思考

常用的ID生成策略

Posted by lijian on March 4, 2019

需求

  • 全局唯一:主键,能不唯一吗,并且是分布式系统内的全局唯一
  • 趋势递增:不一定要求差值1,但是一定要趋势递增,主要是考虑 MySQL 存储策略
  • 高可用,高性能
  • 信息安全:比如使用自增主键做订单号,很容易推测系统的订单量,使用自增主键做传输,恶意用户很容易获取其他用户的信息

方案

1. 数据库自增

查看自增起点和步长 SHOW GLOBAL VARIABLES LIKE ‘auto_incre%’
设置自增起点和步长
set session auto_increment_increment=2; 或者 set global auto_increment_increment=2;

1.1 优点

实现简单

1.2 缺点

数据库迁移时由于不同数据库的实现不同需要处理
一主多从时受到主库单点性能瓶颈限制
多库数据合并ID很有可能冲突

2. UUID

2.1 优点

唯一

2.2 缺点

无序,对于MySQL 存储严重影响性能

3. 三方方案

Redis 自增,ZK 有序节点,MongoDB 的 ObjectID 等

4. twitter Snowflake 及其变种

1 位标识位(常数0,因为0正1负)
41位时间戳(41位的时间截,可以使用69年,年T = (1L « 41) / (1000L * 60 * 60 * 24 * 365) = 69)
10位 workerID(同时部署 1024 个节点)
12位序列(单节点每毫秒4096个ID)
Snowflake 实现
uid-generator 实现

4.1 优点

算法简单
高性能,10w/s

4.2 缺点

时钟偏斜,时钟回拨可能会导致重复
分布式系统的时钟必须严格一致

4.3 拓展

提前生成放入队列(队列可以保证有序),解决批量获取问题
关于获取 workerID 有一种参考实现