分布式架构系统生成全局唯一序列号的一个思路分布式架构系统生成全局唯一序列号的一个思路
一、相关背景
分布式架构下,唯一序列号生成是我们在设计一个系统,尤其是数据库使用分库分表的时候常常会遇见的问题。当分成若干个
sharding表后,如何能够快速拿到一个唯一序列号,是经常遇到的问题。
在携程账号数据库迁移MySQL过程中,我们对用户ID的生成方案进行了新的设计,要求能够支撑携程现有的新用户注册体
量。
二、特性需求
1. 全局唯一
2. 支持高并发
3. 能够体现一定属性
4. 高可靠,容错单点故障
5. 高性能
三、业内方案
生成ID的方法有很多,来适应不同的场景、需求以及性能要求。
常见方式有:
1、利用数据库递增,全数据库唯一。
优点:明显,可控。
缺点:单库单表,数据库压力大。
2、UUID, 生成的是length=32的16进制格式的字符串,如果回退为byte数组共16个byte元素,即UUID是一个128bit长的数
字,一般用16进制表示。
优点:对数据库压力减轻了。
缺点:但是排序怎么办?
此外还有UUID的变种,增加一个时间拼接,但是会造成id非常长。
3、twitter在把存储系统从MySQL迁移到Cassandra的过程中由于Cassandra没有顺序ID生成机制,于是自己开发了一套全局
唯一ID生成服务:Snowflake。
1. 41位的时间序列(精确到毫秒,41位的长度可以使用69年)
2. 10位的机器标识(10位的长度最多支持部署1024个节点)
3. 12位的计数顺序号(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号) 最高位是符号位,始终为0。
优点:高性能,低延迟;独立的应用;按时间有序。
缺点:需要独立的开发和部署。
4、Redis生成ID
当使用数据库来生成ID性能不够要求的时候,我们可以尝试使用Redis来生成ID。这主要依赖于Redis是单线程的,所以也可
以用生成全局唯一的ID。可以用Redis的原子操作INCR和INCRBY来实现。
可以使用Redis集群来获取更高的吞吐量。假如一个集群中有5台Redis。可以初始化每台Redis的值分别是1,2,3,4,5,然后步
长都是5。各个Redis生成的ID为:
A:1,6,11,16,21
B:2,7,12,17,22