分布式 id
分布式 id 需要处理的问题主要是同一时间在多台机器中保证生成的 id 唯一,需要满足全局唯一、高性能、高可用、有序递增、安全性等要求,为了这么做我们可以这么做:
# 分布式 id 生成策略
先说几个已经被淘汰的策略引出分布式 id 的问题
1,UUID:UUID 全称为通用唯一识别码,是由一组32位数的16进制数字所构成,是故 UUID 理论上的总数为16^32 = 2^128,约等于3.4 x 10^38。也就是说若每纳秒产生1兆个 UUID,要花100亿年才会将所有 UUID 用完,UUID 随机并且唯一,在单一的数据库中就不适合作为主键,因为生成的字符串太长不符合索引优化规则
2,自增 ID:不管是数据库自增还是 MP 自增,分布式数据库中总是要存放一定范围的数据
以下生成分布式 id 的方法比较靠谱
3,redis 生成:利用 redis 的 incr 命令生成 id
4,雪花算法:生成一个64bit 的 id,也就是 long 类型的数字,长度适中并且方便快捷
5, 使用一些开源框架
- Leaf:支持双号段、Zookeeper 管理 workId,QPS 可达5w/s
- Tinyid:基于号段模式,支持本地客户端生成,减少网络开销
- IdGenerator:跨语言实现,解决时间回拨,支持手工插入历史 ID
6,可以使用分片键结合自增,比如5台机器,步长就是5,每个机器生成一次id,该机器 id 就加5
# 雪花算法
雪花算法是一个比较常见的生成分布式 id 的方式,它会生成一个 8 字节的数据,通过确保每段数据在空间与时间上唯一来确定最终数据的唯一
64bit 中,起始 1bit 为0,闲置不用
接下来 41bit 代表时间戳,这个是毫秒级的时间,存放时间戳的差值(当前时间-固定的开始时间),41位的时间戳可以使用69年
10bit 存放机器 id,前 5bit 代表机器位置(配置在不同地区的机器有不同 id),后 5bit 代表机器 id (一个地区会配置集群)
最后的 12bit 代表流水号,一个毫秒时间内最多可以处理4096个 id
最后雪花算法会生成 long 类型的数字,用于当唯一 ID 再合适不过
# UUID 与自增 ID 的优缺点
对于所有的 UUID 它可以保证在空间和时间上的唯一性。它是通过 MAC 地址,时间戳,随机数等数据来保证生成 ID 的唯一性,有着固定的大小(128bit)。因此它可以用于分布式的生产环境,以支持更高的并发
它的缺点是更占用空间,并且存放的是 varchar 类型,在通过 ID 查找的时候的效率很低
无序,随机生成与插入,聚集索引频繁页分裂,大量随机 IO,内存碎片化,特别是随着数据量越来越多,插入性能会越差
因此在并发数不是很高的情况下使用自增 ID 是不错的方法,主键页以近乎顺序的方式填写,提升了页的利用率。索引更加紧凑,性能更好查询时数据访问更快,连续增长的值能避免 b+ 树频繁合并和分裂