对于一般应用来说,通常会需要用到业务唯一编码,比如订单流水号、操作记录流水号,关于它的生成方式有多种可以选择。

分布式ID.png

1、UUID

UUID 使用非常简单,全球唯一、本地生成,缺点是没有业务含义,且不能自增,作为数据库的字段有些太长。


UUID.randomUUID().toString()

2、数据库自增 ID

Orale 的序列 sequence,MySQL 的 auto increment 自增 ID,都可以作为分布式应用的 ID 生成。其优点是数字类型,并且可以自增。
当然缺点就是并发场景下的性能瓶颈。

3、基于数据库的号段模式

号段模式的思想是每次从数据库中取出一批 ID 供程序使用,从表中获取本次起始值和步长,如 [1,1000],采用 version 作为乐观锁来保证并发时的数据正确性。
其优点是相对数据库自增 ID ,对数据库的查询压力减少很多,不用频繁访问。

4、Redis 或 Zookeeper 实现

redis 中的 incr 命令,可以实现原子自增。


redis> SET test_id 20
OK

redis> INCR test_id
(integer) 21

redis> GET test_id    # 数字值在 Redis 中以字符串的形式保存
"21"

相比较而言,redis 可支撑的并发量非常高,性能好,但是需要考虑宕机后主从切换时,由于主从数据同步延迟造成的数据不一致问题。

基于 Zookeeper 也可以实现分布式的自增序列,通过 Apache Curator 提供的 DistributedAtomicLong 来获取。Apache Curator 是一个比较完善的 Zookeeper 客户端框架,简化了客户端与 ZK 服务端的交互。

DistributedAtomicLong,A counter that attempts atomic increments. It first tries using optimistic locking. If that fails, an optional InterProcessMutex is taken. For both optimistic and mutex, a retry policy is used to retry the increment .


AtomicValue<Long> sequence = distAtomicLong.increment();
if (sequence.succeeded()) {
    Long seq = sequence.postValue();
}

5、Snowflake

Snowflake ,雪花算法,是 Twitter 公司开源的一个分布式 ID 生成算法。其算法根据时间戳、机器号、数据中心号、自增值等等成一个 64 位的 Long 类型值。

基于 ID 生成的算法,不依赖其它系统或数据库,以服务的方式部署,供其它服务调用,稳定性高,生成 ID 的性能也非常高。其缺点是强依赖于时间戳,如果机器上时钟回拨,会导致重复 ID 的生成。

6、Tinyid

Tinyid,是滴滴开源的分布式 ID 生成方案, https://github.com/didi/tinyid
其思想是基于数据的号段模式来生成 ID,架构图如下:

原理如下:

Tinyid 是基于数据库发号算法实现的,简单来说是数据库中保存了可用的 id 号段,tinyid 会将可用号段加载到内存中,之后生成 id 会直接内存中产生。
可用号段在第一次获取 id 时加载,如当前号段使用达到一定量时,会异步加载下一可用号段,保证内存中始终有可用号段。
(如可用号段 1~1000 被加载到内存,则获取 id 时,会从 1 开始递增获取,当使用到一定百分比时,如 20% (默认),即 200 时,会异步加载下一可用号段到内存,假设新加载的号段是 1001~2000,则此时内存中可用号段为 200~1000,1001~2000),当 id 递增到 1000 时,当前号段使用完毕,下一号段会替换为当前号段。依次类推。

7、Uidgenerator

Uidgenerator,是百度开源的分布式 ID 生成方案,https://github.com/baidu/uid-generator
Uidgenerator 是基于 Snowflake,并且对 ID 组成部分的位数做了调整,并支持自定义。它需要数据库 worker_node 表来存储工作节点 。

8、Leaf

Leaf,是美团开源的分布式 ID 生成方案,https://github.com/Meituan-Dianping/Leaf
Leaf 提供两种生成的ID的方式,号段模式和 snowflake 模式,可通过配置文件来指定。
Leaf 的雪花算法模式依赖于 ZooKeeper,在 workId 的生成策略上,是基于 ZooKeeper 的顺序 ID 来生成的,每个应用在使用 Leaf-snowflake 时,启动时都会都在 Zookeeper 中生成一个顺序 ID,相当于一台机器对应一个顺序节点,也就是一个 workId。