中级系统设计常考。Snowflake白板画得下、细节又够多,面试官特别爱问。
Snowflake(Twitter原版)布局:1符号位+41时间戳位(毫秒)+10工作节点位+12序列位=64位long。
41位毫秒够用69年。10位workerID=1024个节点。12位序列=每节点每毫秒4096个。
核心坑:时钟回拨。NTP倒拨时钟就会生成重复ID。缓解:拒绝生成、等到追上、借用序列位。
备选方案:UUID v4(128位随机,不有序——B+树插入烂)、号段模式(从DB取[a,b]本地发——美团Leaf-segment)、Leaf-snowflake(Zookeeper派workerID)。
数据库原生:TiDB AUTO_RANDOM、Postgres pg_ulid。如果已经在用这些DB可以直接白嫖。
没特殊理由我默认snowflake——64位long各处都塞得下、大致有序、4096每毫秒每节点管够。坑就是时钟回拨,我见过一次NTP bug把时钟倒拨500ms生成了重复。所以我的生成器记录last timestamp,一旦回拨就拒发、报警、等追回来。workerID用Zookeeper顺序znode分配,扩容自动化。超高写入场景我会加号段模式兜底。UUID v4我只用在DB外(请求ID、幂等键),随机ID会把B+树插入局部性毁掉。
随机UUID做主键能让插入吞吐砍一半——这坑是真的。
时钟漂移担心?编一个"回拨次数"位,拨一次翻一次,不动时间戳。
即答侠会让你默写比特位布局——面试现场自信画出来,印象分加满。
自增是单库的。分库分表要么中心化(瓶颈)要么冲突。分布式生成器把ID从DB解耦。
号段单调递增、容易猜(对公开URL不安全);snowflake大致有序但不连续。内部业务ID用号段,不希望被猜的场景用snowflake。