分布式ID
需求
- 全局唯一
- 高性能
- 高可用
- 简单易用
UUID
优点:
- 唯一
- 不依赖于任何第三方服务
缺点:
- 是字符串类型而非数字,不满足数字ID的需求
- 字符串太长了,DB查询效率受影响
数据库自增ID
如果使用 mysql 单实例:性能可能不够;单实例的稳定性不强,宕机会影响业务
如何解决稳定性问题呢?
方案一:使用主从模式集群
存在的问题:满足了高可用,但数据同步延时问题可能导致ID重复。
方案二:使用多主机主从模式集群,对多主机做高可用
必须设置自增起始值与步长
举例:比如两个主机 master1 只会产生奇数ID,master2 只会产生偶数ID
存在的问题:
- 性能依旧不足,每次都去请求数据库
- 如果再新增一个主,扩展起来麻烦
如何解决性能问题呢?
方案三:使用号段模式,批量从数据库获取ID缓存起来,缓存中的ID一旦达到上限就再次去数据库批量获取
DB设计如下:
- biz_type 代表业务类型,业务隔离
- max_id 代表当前最大的可用 id
- step 代表号段的长度,合理设置即可
- version 是一个乐观锁,用来保证并发更新的正确性
最终方案
最终方案结合方案二和方案三的优点,DB设计如下:
- delta 表示缓存中的 ID 每次增量
- remainder 代表余数
缺点:
- 扩展主机个数麻烦
- 实现复杂
雪花算法
- 使用一个 long 类型作为 ID
- 64位:第一位0表示正数 + 41位毫秒级时间戳 + 10位主机编号 + 12位序列号
- 时间戳通常是相对时间,这样可用期限就更长,理论上支持 69 年
- 支持 1024-1=1023 个主机节点
- 支持同一个时间点同一台服务器生成 4096-1=4095 个序列号
主机编号手动分配太麻烦了,可以在 Zookeeper 中创建序列节点,用节点序号(缓存起来)作为主机编号。
优点:快
相关文章:
//www.liaoxuefeng.com/article/1280526512029729
//www.cnblogs.com/wuneng/p/11478160.html
//github.com/didi/tinyid/wiki/tinyid原理介绍
//mp.weixin.qq.com/s/hz7TntFDurwkAaSGODbF-Q