← 每日面试题 学习看板

什么是雪花算法,怎么保证不重复的?

面试题/02架构设计题/02分布式/04分布式ID生成/什么是雪花算法,怎么保证不重复的?.md

面试记录 2026-10-10

题目:什么是雪花算法,怎么保证不重复的?

难度:low

标签:arch/distributed/id, distributed/snowflake, difficulty/low

评分:⭐⭐⭐⭐☆(4/5)

我的回答

首先,雪花算法是一个用于生成分布式 ID 的,用于本地生成分布式 ID 的算法。它的核心是通过分段的方式,使用多段,一整个数据的多个数位来生成单调递增的,或者说区域递增的 ID 的一个方式,一个算法。其中有一部分数位是时间戳,用来保证 ID 的自增性。然后通过机器码来保证不同机器生成不同的 ID。通过最后的一部分随机的数位,来保证当前机器上,同一时间产生的,同一时间戳下产生的 ID 不同。

但是它本身也存在一定问题,比如多个机器上出现时间不统一,虽然不会产生相同的 ID,但可能会产生 ID 倒序的生产,因为它是靠时间戳来生成数据的。另外,如果出现时钟回拨,可能同一个机器上会产生同样的 ID,分布式 ID。但是好处上,它是一个在单机上不需要一个中心的支持的 ID,分布式 ID 生成算法,它可以比较快速的生成分布式 ID。要解决刚刚时钟的问题,可以通过记录最后一个 ID。每一个机器的最后一个 ID 进行缓存,在生成时进行比对,来确保生成的 ID 的正确性和不重复性。

点评

优点:

不足:

补充:

完整讲解

第一部分:知识重点剖析

核心考点定位:考察雪花算法的位结构、去重机制、以及工程落地时的关键风险点。

知识点拆解:

  1. 位结构:1 符号位 + 41 时间戳 + 10 workerId + 12 sequence。41 位毫秒时间戳以 Twitter 2010-11-04 为纪元,可表示 69.7 年
  2. 不重复原理:跨机器靠 workerId 隔离,同机器同时刻靠 sequence 隔离,跨时刻靠 timestamp 递增。三段位保证任意时刻两台机器生成的 ID 必不相等
  3. 优点:本地生成无网络调用,QPS 极高(单机可达 409.6 万/ms);ID 大致随时间递增,对数据库 B+ 树索引友好
  4. 风险 1:workerId 冲突 —— 两个节点被分配同一 workerId,会生成重复 ID。必须先解决 workerId 唯一性
  5. 风险 2:时钟不同步 —— 网络抖动导致节点间时钟偏移,跨节点 ID 非严格递增(但不重复)
  6. 风险 3:时钟回拨 —— NTP 同步导致本地时钟回退,可能生成已用过的 ID。必须在代码层拦截
  7. 常见时钟回拨处理:①容忍小回拨(沿用 lastTimestamp + 递增 sequence);②等待(sleep 到正确时间);③抛异常(超过阈值直接拒绝)
递进:位结构 → 去重原理 → 性能 → 三大风险 → 工程兜底

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. workerId 有几种分配方式?各有什么问题?
  1. 雪花算法生成的 ID 为什么对 B+ 树索引友好?
  1. 单机 409.6 万/ms 用完了怎么办?
  1. 雪花算法和 Leaf 号段方案怎么选?

第三部分:面试者参考回答(300-600 字口语化)

面试官您好,雪花算法是 Twitter 提出的一种本地生成、无中心节点的分布式 ID 算法,核心是用一个 64 位 long 按位分段。标准分配是:最高 1 位保留符号位为 0,接下来 41 位是毫秒级时间戳(以 2010-11-04 为纪元,可表示约 69 年),接下来 10 位是机器 workerId(最多 1024 台机器),最后 12 位是同一毫秒内的自增序列号(4096/ms,即单机 409.6 万 ID/s 上限)。

不重复的保证分两层:跨机器靠 workerId 位段区分,两台机器生成的 ID 在这 10 位上必不相等;同机器同毫秒靠 sequence 位段区分,每秒内最多 4096 个不同序列值。两个 ID 只要任一段不同,全 ID 就不同。

雪花算法的三大工程风险:第一是 workerId 冲突,如果两台机器拿到相同 workerId,去重机制就崩了,所以工程上必须先解决 workerId 分配问题,常见做法是配置文件、ZK 抢锁、或者从 K8s pod 序号取;第二是时钟不同步,跨机器的 ID 会非严格递增,但不重复;第三是时钟回拨,本地 NTP 同步后时钟往前退,可能生成已用过的 ID。

处理时钟回拨业界通常分三档:小回拨(比如小于 5ms)沿用 lastTimestamp 让 sequence 继续递增;中等回拨 sleep 到正确时间再发;超过阈值直接抛异常阻断。核心思路是宁可暂时不发 ID,也不能发重复 ID。

雪花算法的优点是本地生成无网络调用、QPS 极高,且 ID 大致随时间递增,对 MySQL B+ 树索引非常友好,插入几乎总是追加到叶子页右侧。缺点是强依赖机器时钟,且需要维护 workerId 分配。相比 UUID 更适合业务主键场景,相比数据库自增和号段方案更适合对延迟敏感的业务。