需求
- 全局唯一:主键,能不唯一吗,并且是分布式系统内的全局唯一
- 趋势递增:不一定要求差值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 等
1 位标识位(常数0,因为0正1负)
41位时间戳(41位的时间截,可以使用69年,年T = (1L « 41) / (1000L * 60 * 60 * 24 * 365) = 69)
10位 workerID(同时部署 1024 个节点)
12位序列(单节点每毫秒4096个ID)
4.1 优点
算法简单
高性能,10w/s
4.2 缺点
时钟偏斜,时钟回拨可能会导致重复
分布式系统的时钟必须严格一致
4.3 拓展
提前生成放入队列(队列可以保证有序),解决批量获取问题
关于获取 workerID 有一种参考实现