什么是分布式ID#
分布式ID指在多服务器、多节点协同中用于标识唯一资源的全局唯一标识符(Unique Identifier)。
单机的数据库自增ID/内存计数器ID在分布式场景下,因此跨节点、跨服务全局唯一的ID生成机制就诞生了
核心使用场景#
分布式ID核心是“唯一性”。场景有:
- 分布式数据库分库分表;
- 微服务间数据交互
- 分布式事务与追踪
- 高并发场景下的唯一标识
- 如秒杀、抢票等场景中,需快速生成大量唯一订单ID
常见分布式ID生成方案#
UUID/GUID(通用唯一识别码)#
原理:基于MAC地址、时间戳、随机数等生成128位字符串,全球唯一;
优点:简单,Java直接用UUID.randomUUID()
生成,高性能、无中心化(即无需第三方请求)
缺点:
- 无序,如果是数据库主键B+数频繁分裂,性能降低
- 太长:128位,不适合当主键或URL参数
- 无含义,没有业务信息,但是反过来又能保密,避免泄露一些业务信息
数据库自增ID(单库/多库分段)#
是的,虽然在一定程度上分布式ID就是在解决单机数据库自增ID的不唯一,但是仍然可以使用。
- 维护一个独立的ID生成数据库,将ID分发给其他需要的服务;显然,单库自增在高并发下会成为性能瓶颈;而且这个库挂了,业务可能就直接完蛋了()
- 那么单库不行,可以使用多库,用“号端”来预分配ID,就像IPv4地址一样,分为网络号与主机号;缺点是多库分段要手动配置规则,新增节点时容易冲突
号段模式 Segment#
原理:从数据库给服务节点直接预分配一段连续ID,用完后再向数据库申请
优点:高性能(本地生成);有序;可扩展
缺点:依赖数据库,仍有单点风险(可通过主从赋值解决)
典型开源实现:美团Leaf(基于号段模式和雪花算法的混合方案)
Leaf——美团点评分布式ID生成系统 - 美团技术团队 ↗
PS:之前就听说过美团技术团队的博客,这次在学习这里的时候遇到了
雪花算法 Snowflake(最常用)#
这是Twitter开源的分布式ID生成算法,生成64位Long型ID,结构如下:
0 | 41位时间戳 | 10位工作机器ID | 12位序列号
1位符号位+41位时间戳(ms级)+10位机器ID(支持1024个节点)+12位序列号(每ms最多生成4096个ID)
markdown- 有符号的64位Long型最高位是符号位,0正1负
- 时间戳确保ID随时间递增,能用69年
- 机器ID:标识节点,可以通过配置或者ZooKeeper分配
- 序列号,解决同一毫秒内的节点生成的ID序号生成问题
优点:
- 高性能,还是本地生成,远端生成有网络IO延迟,每秒可以生成百万级ID(1000ms*4096)
- 有序
- 紧凑:64位Long型,存储成本低,适合作数据库主键
缺点:
- 强依赖时钟:若节点时钟回拨,像服务器时间校准,可能生成重复ID
- 需要进行机器ID管理
典型开源实现:百度UidGenerator,优化雪花算法,支持自定义时间戳位数、机器ID位数,Java中可以直接手写实现;
Redis自增ID#
Redis的INCRBY生成自增ID,Redis单线程,命令是原子的,故此能保证其唯一性
优点无需多言,就是Redis的优势(高性能、集群分布式、简单)
缺点:
- 依赖Redis:Redis宕机时无法生成ID,game over了;主从+哨兵可以保证高可用
- ID无序性:跨Redis节点不同分片可能无序,但是设置不同分片起始偏移量可以解决
- 适用:对ID有序性要求不严格