雪花算法一种分布式主键生成算法

雪花算法(Snowflake)是 Twitter(现 X)开源的一种分布式主键生成算法。它的核心作用是:在分布式系统中,生成全局唯一且趋势递增的 64 位整型 ID

在单机环境中,我们可以简单地使用数据库的自增 ID,但在高并发的分布式微服务架构中,不同机器如果同时生成 ID 就会产生冲突。雪花算法就是为了解决这个问题而诞生的。


1.雪花算法的 ID 结构

雪花算法生成的 64 位(bit)二进制整数,在实际使用中通常被划分为 4 个核心部分:

  • 1 bit(不用): 固定为 0。因为二进制中最高位是符号位,0 表示正数,1 表示负数。我们生成的 ID 一般都是正整数,所以最高位固定为 0。

  • 41 bit(时间戳): 记录毫秒级时间戳。41 位的二进制可以表示 $2^{41} - 1$ 毫秒,换算下来大约可以使用 69 年

  • 10 bit(工作机器 ID): 用来区分不同的机器。可以容纳 $2^{10} = 1024$ 个节点。通常这 10 位会被拆分为:

  • 5 bit:机房 ID(DataCenter ID,最多 32 个机房)

  • 5 bit:机器 ID(Worker ID,每个机房最多 32 台机器)

  • 12 bit(序列号): 计数器,用于同一机器、同一毫秒内产生不同的 ID。12 位可以表示 $2^{12} = 4096$ 个数字。也就是说,单台机器在 1 毫秒内最多可以生成 4096 个唯一的 ID

理论最大并发量: 1024 台机器 × 每毫秒 4096 个 ID = 每秒约 400 万个 ID


2.雪花算法的优势

组合:时间戳 + 机器 ID + 序列号

  • 全局唯一: 通过组合:时间戳 + 机器 ID + 序列号的组合,保证了在全网任何一台机器上生成的 ID 都是独一无二的。
  • 趋势递增: 整个 ID 的高位是时间戳,这意味着随着时间的推移,新生成的 ID 一定比旧的 ID 大。这对于数据库索引(如 MySQL 的 B+ 树)非常友好,能大大提高写入效率。
  • 高性能、低延迟: 生成 ID 的过程完全在本地内存中进行,不依赖数据库或第三方缓存(如 Redis),没有网络开销,效率极高。

3.核心痛点:时钟回拨问题

雪花算法非常依赖系统的时间戳。如果服务器的本地时钟因为校准、人工修改等原因向后调整了(即时钟回拨),算法就会面临生成重复 ID 的风险。

常见的解决思路:

  1. 直接抛出异常: 如果发现当前时间小于最后一次生成 ID 的时间,说明发生了时钟回拨,直接报错,拒绝提供服务。
  2. 等待时钟追回: 如果回拨的时间很短(例如几毫秒),可以让线程睡眠等待几毫秒,等时间追上后再继续生成。
  3. 使用历史时间/预留机器码: 比较复杂的分布式方案会通过逻辑时钟或备用机器 ID 来继续生成 ID。