分布式全局ID生成方案
分布式服务架构模式下分库分表的设计,使得多个库或多个表存储相同的业务数据,故而需要生成全局唯一的有序(部分有序)
ID
来记录数据,保证数据的唯一性。
UUID 生成方案一
UUID(Universally Unique Identifier)
, 通用唯一识别码。UUID
是由一组32位数的16进制数字所构成,所以UUID理论上的总数为16^32=2^128
,约等于3.4 x 10^38
。也就是说若每纳秒产生1兆个UUID
,要花100亿
年才会将所有UUID
用完。- 生成的
UUID
是由8-4-4-4-12
格式的数据组成,其中32个字符和4个连字符' - '
,一般我们使用的时候会将连字符删除uuid.toString().replaceAll("-","")
生成方式 | 组合 | 优点 | 缺点 |
---|---|---|---|
基于时间 | 前时间+随机数+mac地址 | mac地址确保唯一性 | 暴露mac地址 |
DCE安全 | 和基于时间的UUID算法相同,但会把 时间戳的前4位置换为POSIX的UID或GID |
同上 | 同上 |
随机 | 随机产生,JDK中使用 | 重复的可能性可以忽略不计 | 无序 |
基于名字MD5 | 名字+MD5(命名空间) | 有命名空间隔离 | 相同命名空间同名的UUID相同 |
基于名字SHA | 名字+SHA(命名空间) | 同上 | 同上 |
注:
DCE:Distributed Computing Environment
总体优点
UUID
生成方便,本地生成没有网络消耗
总体缺点
- 不易于存储:
UUID
太长,16字节128位,通常以36长度的字符串表示,很多场景不适用。- 信息不安全:基于
MAC
地址生成UUID
的算法可能会造成MAC地址泄露,暴露使用者的位置。- 对
MySQL
索引不利:如果作为数据库主键,在InnoDB
引擎下,UUID
的无序性可能会引起数据位置频繁变动,严重影响性能。
基于数据库实现
对与分数据库的场景比如4个库,每个库先分配一个起始ID(1..4)
,每个库的ID在之前的ID基础上加4(数据库的个数)
如下所示
- DB1: 1,5,9,…
- DB2: 2, 6, 10, …
- DB3: 3, 7, 11, …
- DB4: 4, 8, 12, …
优点
只依赖于数据库本身,ID号单调递增,无重复
缺点
无法扩展
redis实现
原理
Redis
实现分布式唯一ID主要是通过提供像INCR
和INCRBY
这样的自增原子命令,由于Redis自身的单线程的特点,所以能保证生成的 ID 肯定是唯一有序的。
缺点
redis
是单线程生成,存在性能瓶颈,依赖于redis,需要系统引进redis组件,增加了系统的配置复杂性
Snowflake
Snowflake,Twitter
开源的分布式ID生成算法
组成如下
1bit |
41bit |
10bit |
12bit |
---|---|---|---|
0 | 时间戳 | 机器数 | 自增序列 |
符号位不使用 |
(1L<<41)/(1000L*360024*365)=69年 |
2^10=1024 |
2^12=4096 |
优点
id呈递增趋势,不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的,而且可以根据自身业务特性分配bit位,非常灵活。
缺点
如果发生时钟回拨,就可能产生重复的ID。