分布式 ID 实现方案

数据库

数据库主键自增

使用 replace into 命令来插入数据,通过 MySQL 的自增主键来产生唯一 ID。

  • 优点:实现简单,ID 有序递增,存储空间消耗小。
  • 缺点:并发量小,每次获取 ID 都要访问数据库导致数据库的压力很大。

数据库号段模式

可以每次从数据库申请一个号段,也就是一个 ID 的范围,加载到内存中,需要用到的时候,直接从内存里通过自增的方式来生成 ID。一个号段的 ID 用完后可以再次向数据库中申请。

NoSQL

Redis

可以通过 Redis 的 incr 命令来实现 ID 的原子顺序递增。

MongoDB

使用 MongoDB 的 ObjectId 来生成分布式 ID:

4位时间戳、3位机器 ID、2位机器进程 ID、3位自增值

算法

UUID

UUID 是 Universally Unique Identifier(通用唯一标识符)的缩写。UUID 包含32个16进制的数字。

可以直接使用 Java 的 UUID.randomUUID() 方法直接生成。

Snowflake(雪花算法)

传统的雪花算法是由64bit的二进制数字组成。

  • sign(1bit):符号位(标识正负),始终为 0,代表生成的 ID 为正数。
  • timestamp (41 bits):一共 41 位,表示时间戳,单位是毫秒,可以支撑 约 69 年。
  • datacenter id + worker id (10 bits):一般前 5 位表示机房 ID,后 5 位表示机器 ID。这样就可以区分不同集群/机房的节点。
  • sequence (12 bits):一共 12 位,表示序列号。 序列号为自增值,代表单台机器每毫秒能够产生的最大 ID 数,最多可以生成 4096 个 唯一 ID。

但是雪花算法有个很严重的问题,会产生重复 ID。雪花算法 ID 的生成依赖时间,在获取当前时间的时候,服务器上的时间可能会突然倒退到之前的时间,也叫做时间回拨,进而导致重复的 ID。

Seata 改良的雪花算法

标准版雪花算法的缺点

时钟敏感

因为 ID 的生成是和当前操作系统的时间绑定的,如果操作系统发生了时钟回拨现象,生成的 ID 就会重复。

突发性能有上限

时间戳单位是毫秒,而分配给序列号的位长度为12,即每毫秒4096个序列空间。所以 QPS 是 4096/ms。

解决方案

为了解决时钟敏感问题,解除与操作系统时间戳的时刻绑定,生成器只在初始化时获取系统当前的时间戳,作为初始时间戳, 但之后就不再与系统时间戳保持同步了。它之后的递增,只由序列号的递增来驱动。

为了方便这种溢出进位,调整64位 ID 的分配策略:

  • sign(1bit):符号位始终为 0。
  • datacenter id + worker id (10 bits):节点 ID。
  • timestamp (41 bits):一共 41 位,表示时间戳。
  • sequence (12 bits):一共 12 位,表示序列号。

这样时间戳和序列号在内存上是连在一块的,在实现上就很容易用一个 AtomicLong 来同时保存它俩,最高11位可以在初始化时就确定好,之后不再变化。

这样我们可以发现:

  • 生成器不再有 4096/ms 的突发性能限制了。如果某个时间戳的序列号空间耗尽,它会直接推进到下一个时间戳, “借用”下一个时间戳的序列号空间。
  • 生成器弱依赖于操作系统时钟。在运行期间,生成器不受时钟回拨的影响,因为生成器仅在启动时获取了一遍系统时钟,之后两者不再保持同步。唯一可能产生重复 ID 的只有在重启时的大幅度时钟回拨,比如人为刻意回拨或者修改操作系统时区,如北京时间改为伦敦时间。机器时钟漂移基本是毫秒级的,不会有这么大的幅度。
  • 持续不断的”超前消费”实际上并不会使生成器内的时间戳大大超前于系统的时间戳, 从而在重启时造成 ID 重复。因为要达到这种效果,意味该生成器接收的 QPS 得持续稳定在 400w/s 之上。流量太高了。

节点 ID 优先从本机网卡的 MAC 地址截取低10位,如果本机未配置有效的网卡,则在[0, 1023]中随机挑一个作为节点 ID。

 

PS:参考文章

1、分布式ID介绍&实现方案总结 | JavaGuide

2、Seata基于改良版雪花算法的分布式UUID生成器分析 | Apache Seata

评论

  1. 213
    2 月前
    2025-9-12 23:21:50

    I am a rot

  2. 233
    2 月前
    2025-9-12 23:00:44

    233

  3. 233
    2 月前
    2025-9-12 22:32:20

    跪了

  4. 233
    2 月前
    2025-9-12 22:23:45

    沙发

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇