雪花算法
约 450 字大约 2 分钟
2025-09-03
用于解决分布式 ID 的生成,需要满足唯一性与顺序性
构成
由 64 位构成,对应 Java 中的 long 
- 第 1-12 位:序列号,用于同一机器并发执行获取的时间相同时的区分
- 第 13-22 位:示例标志,用于标定机器的 ID,分布式中可以为左边 5 位是机器 ID,右边 5 位是机房 ID
- 第 23-63 位:时间戳,可以设置当前时间与起始时间的差值,以充分利用长度
- 第 64 位:表示正数,为 0
构建
思路
- 时间戳:获取当前时间戳并减去开始时间,向左移动(12 + 10)22 位
- 机器 ID:向左移动 17 位
- 机房 ID:向左移动 12 位
- 序列号:位于最右端,无需移动
时钟回拨
为了保证唯一性,小于记录的上一次时间戳的时间戳都是不可用的假如说因为服务器时间同步或是其他原因,当前时间被回拨了,即currentTimestamp < lastTimestamp的情况
- 直接抛出异常
- 等待,直到过了上一次记录的时间
- 尝试使用更高精度的时间戳
序列号溢出
对于12位序列号,若并发线程数大于 4096,则有可能出现序列号抢通的情况 可以设置一个掩码,通过将当前序列号与掩码与操作确定是否溢出,若溢出了可以等到下一毫秒的到来再行动
序列号(假设只有 4 位):
0000 1111
此时加一
0001 0000
我们只需要设置一个掩码:0000 1111
0001 0000
&
0000 1111
= 0 => 溢出