常见生成方式
UUID
- 标准型式包含 32 个 16 进制数字,以连字号分为五段,形式为 8-4-4-4-12 的 36 个字符
- 性能非常高,本地生成,没有网络消耗
- UUID.randomUUID().toString()
为什么无序的 UUID 会导致入库性能变差
- 分布式 ID 一般会作为主键,MySQL推荐主键尽量越短越好,所以不是很推荐。同时UUID生成为无序的,不能生成递增有序的数字
- 由于 MYSQL 的索引通过 B+ 树实现的,每一次新的 UUID 数据的插入,为了查询的优化都会对索引底层的 B+ 树进行修改,因为 UUID 无序所以每一次插入都会对主键的 B+ 树进行很大的修改,可能会导致一些中间节点产生分裂,也会创造很多不饱和节点,降低了数据库插入的性能
数据库主键自增
- 自增 ID 机制的主要原理是:数据库自增 ID 和 MySQL 数据库的replace into 实现
- replace into 的含义是 插入一条记录,如果表中唯一索引的值遇到冲突,则替换老数据
缺点
- 系统水平拓展比较困难,需要定义步长和初始值来实现,配置麻烦,利用率低
- 数据库压力大,每次获取 ID都得读写一次数据库,非常影响性能,不符合分布式 ID 里面的低延迟和高 QPS 要求
基于 Redis 生成全局 ID
- 与 MySQL 类似,好处是可以获取更高的吞吐量,同时也需要设置步长和增长,key一定要设置有效期
雪花算法
- 官网
- Twitter 的分布式自增 ID 算法 snowflake
- 集群高并发情况下保证分布式唯一全局 ID 生成,生成的 ID 能过按照时间有序生成,结果是一个 64 bit 大小的整数,为一个 Long 性;分布式系统内不会产生 ID 碰撞(由 datacenter 和 workerID 区分)并且效率较高
- 41 bit 用来记录时间戳,毫秒级;12 bit 用来记录同毫秒内产生的不同 ID
- 10 bit 工作进程位,用来记录工作机器ID, 一般分为 5 datacenter 和 5 workerID
分布式全局 ID 要求
- 全局唯一
- 趋势递增
- 单调递增
- 信息安全
- 含时间戳
优势与劣势
- 毫秒数在高位,自增序列在低位,整个 ID 都是趋势递增的
- 不依赖数据库等第三方系统,以服务的方式部署,稳定性、生成 ID 的性能高
- 可以根据自身业务特性分配 bit 位,相对灵活
- 依赖机器时钟,如果机器时钟回拨会导致重复 ID 生成
拓展
- 百度开源的分布式唯一 ID 生成器 UidGenerator
- 美团点评分布式 ID 生成系统 Leaf