分布式系统全局唯一ID生成器
分布式系统全局唯一ID生成器
代码实现示例repo地址
使用场景一般:
-
分布式系统设计时,数据分片场景下,通常需要一个全局唯一id;
-
在消息系统中需要消息唯一ID标识来防止消息重复;
-
多系统打通需要一个全局唯一标识 (如集团各业务线面对不同用户,需要一个全局用户id);
一般有三种方式实现:
-
UUID
Universally Unique Identifier 是自由软件基金会组织制定的唯一辨识ID生成标准,大多数系统已实现,如微软的GUID实现。
生成格式如:3d422567-f034-4ab4-b98f-a34fd263d0de。
-
sequence
使用数据库维护一张映射表,使用主键自增生成唯一ID。
-
SnowFlake
Twitter实现的算法,使用时间戳+机器分配标识+自增序列组成64位数字ID。
生成格式如:1292755860950487050
UUID
实现可通过以下方式:
-
google方案:https://github.com/google/uuid
-
linux命令:
/usr/bin/uuidgen
优点:性能高,本地生成,无依赖。
缺点:生成格式太长,不适合做数据库主键id,基于mac地址生成算法可能导致mac地址泄漏。
sequece
实现的时候需要注意并发写读,使用事务进行解决。
在冗余服务部署时,可部署多个库表且设置不同step,让每个sequence产生不同id。
可提前进行分配id然后加载到业务中,可减少数据库IO操作,提高性能。
优点:ID单调递增,方便排序,且方案成熟部署简单。
缺点:依赖DB,若为单节点则有性能瓶颈,若为主从架构则需要注意主从一致性问题。
SnowFlake
-
1位最高位:符号位不使用;
-
41位时间戳:2^41-1个数字代表69年,所以设置发号起始时间最好为发号器首次运行时间 ;
-
10位工作机器id:也会分为5位datacenterId和5位workerId ;
-
12位序列号:2^12-1个数字总共4095,同一毫秒同一机器节点可以并发产生4095个不同Id;
在部署上面,不同机器使用不同DatacenterId(数据中心集群id)和WorkerId (机器节点id),最多可部署1024个节点。
多节点部署时,可使用zookeeper做节点分布式协调进行一致性管理,当出现时钟回拨可由zk来同步时间或摘除节点。
优点:ID呈递增趋势,满足排序场景,不依赖于其他组件且易于维护。
缺点:依赖机器时钟,会因为时钟回拨问题会导致发号重复或不可用,代码实现时采用循环等待下一时钟的方式,可能会有性能问题。
总结
UUID | sequence | snowflake | |
---|---|---|---|
描述 | 集成在标准系统中可简单生成 | 使用DB自增id实现 | 根据时间+机器分配标识+自增序列生成 |
依赖 | 无 | DB | 无 |
优点 | 本地生成性能高 | 部署简单生成ID单调递增 | 部署简单生成ID单调递增 |
缺点 | 生成号码复杂,很多场景不利于使用 | 依赖DB有性能问题和重复发号问题号码存在规律会泄露信息 | 依赖系统时钟,时钟回拨会造成重复发号问题 |
针对sequence表方式、snowflake方式的缺点,美团leaf给出了更详细的优化方案可以参考,这里就不过多引用,直接查看参考文档。