1. UUID
UUID经由一定的算法机器生成,为了保证UUID的唯一性,规范定义了包括网卡MAC地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素,以及从这些元素生成UUID的算法。
优点:
- 本地生成ID,不需要进行远程调用,时延低,性能高。
缺点:
- UUID过长,16字节128位,通常以36长度的字符串表示,很多场景不适用,比如用UUID做数据库索引字段。
- 没有排序,无法保证趋势递增。
2. Flicker方案
主要思路采用了MySQL自增长ID的机制(auto_increment + replace into)
#每次业务使用下列SQL读写MySQL得到ID号
REPLACE INTO Tickets64 (stub) VALUES ('a');
SELECT LAST_INSERT_ID();
replace into 跟 insert 功能类似,不同点在于:replace into 首先尝试插入数据到表中,如果发现表中已经有此行数据(根据主键或者唯-索引判断)则先删除此行数据,然后插入新的数据, 否则直接插入新数据。
为了避免单点故障,最少需要两个数据库实例,通过区分auto_increment的起始值和步长来生成奇偶数的ID。
优点:
- 充分借助数据库的自增ID机制,可靠性高,生成有序的ID。
缺点:
- ID生成性能依赖单台数据库读写性能。
- 依赖数据库,当数据库异常时整个系统不可用。
3. 类snowflake方案
这种方案生成一个64bit的数字,64bit被划分成多个段,分别表示时间戳、机器编码、序号。
ID为64bit 的long 数字,由三部分组成:
- 41位的时间序列(精确到毫秒,41位的长度可以使用69年)。
- 10位的机器标识(10位的长度最多支持部署1024个节点)。
- 12位的计数顺序号(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)。
优点:
- 时间戳在高位,自增序列在低位,整个ID是趋势递增的,按照时间有序。
- 性能高,每秒可生成几百万ID。
- 可以根据自身业务需求灵活调整bit位划分,满足不同需求。
缺点:
- 依赖机器时钟,如果机器时钟回拨,会导致重复ID生成。
- 在单机上是递增的,但是由于涉及到分布式环境,每台机器上的时钟不可能完全同步,有时候会出现不是全局递增的情况。
4. TDDL序列生成方式
TDDL是阿里的分库分表中间件,它里面包含了全局数据库ID的生成方式,主要思路:
- 使用数据库同步ID信息。
- 每次批量取一定数量的可用ID在内存中,使用完后,再请求数据库重新获取下一批可用ID,每次获取的可用ID数量由步长控制,实际业务中可根据使用速度进行配置。
- 每个业务可以给自己的序列起个唯一的名字,隔离各个业务系统的ID。
优点:
- 相比flicker方案,大大降低数据库写压力,数据库不再是性能瓶颈。
- 相比flicker方案,生成ID性能大幅度提高,因为获取一个可用号段后在内存中直接分配,相对于每次读取数据库性能提高了几个量级。
- 不同业务不同的ID需求可以用seqName字段区分,每个seqName的ID获取相互隔离,互不影响。
缺点:
- 强依赖数据库,当数据库异常时整个系统不可用