当前位置: 首页 > news >正文

孤舟笔记 分布式与微服务篇十八 雪花算法是怎么实现的?64位里藏着时间、机器和序列号

文章目录

    • 先说结论
    • 64 位详解
    • ID 生成流程
    • 时钟回拨:最大的坑
    • 机器 ID 怎么分配
    • 回答技巧与点评
      • 加分回答
      • 面试官点评

个人网站

前面概要讲了分布式 ID 方案,这道题深入雪花算法的实现细节。面试官问这题,他想听的是:你能不能讲清 64 位的分配、ID 的生成流程、时钟回拨的处理?

先说结论

维度说明
结构1位符号 + 41位时间戳 + 5位数据中心 + 5位机器ID + 12位序列号
时间戳毫秒级,可用约 69 年
数据中心0-31,最多 32 个机房
机器ID0-31,每机房最多 32 台机器
序列号0-4095,每毫秒最多 4096 个 ID
总容量每毫秒 4096 × 1024 台机器 = 419 万 ID/毫秒

|一句话记住:雪花ID像"身份证号"——前6位是地区(数据中心+机器),中间是出生日期(时间戳),后4位是同日序号(序列号)"

64 位详解

┌─────────────────────────────────────────────────────────────────┐ | 0 | 00000000 00000000 00000000 00000000 00000000 0 | 00000 | 00000 | 000000000000 | └─────────────────────────────────────────────────────────────────┘ 1bit 41bit 5bit 5bit 12bit 符号位 时间戳(毫秒) 数据中心 机器ID 序列号 永远为0 (当前时间-纪元) (0-31) (0-31) (0-4095)

41 位时间戳能撑多久?

2^41 - 1 = 2,199,023,255,551 毫秒 ≈ 2,199,023,255 秒 ≈ 69.73 年 纪元通常设为 2020-01-01 00:00:00 → 可用到约 2089 年 👈

10 位机器 ID 能支持多少台机器?

5 位数据中心 × 5 位机器 = 32 × 32 = 1,024 台机器

12 位序列号每毫秒多少个 ID?

2^12 = 4,096 个 ID/毫秒 ≈ 409 万 ID/秒 👈 完全够用

ID 生成流程

publicclassSnowflakeIdGenerator{privatefinallongepoch=1609459200000L;// 2021-01-01 00:00:00privatefinallongdatacenterId;// 数据中心ID (0-31)privatefinallongworkerId;// 机器ID (0-31)privatelongsequence=0;// 序列号privatelonglastTimestamp=-1;// 上次时间戳publicsynchronizedlongnextId(){longtimestamp=System.currentTimeMillis();// 1. 时钟回拨检测 👈if(timestamp<lastTimestamp){thrownewRuntimeException("时钟回拨!");}// 2. 同一毫秒内 → 序列号递增if(timestamp==lastTimestamp){sequence=(sequence+1)&0xFFF;// 12位掩码,最大4095if(sequence==0){// 序列号溢出 → 等下一毫秒timestamp=waitNextMillis(lastTimestamp);}}else{// 3. 新毫秒 → 序列号归零sequence=0;}lastTimestamp=timestamp;// 4. 拼装 ID 👈return((timestamp-epoch)<<22)// 时间戳部分(左移22位)|(datacenterId<<17)// 数据中心(左移17位)|(workerId<<12)// 机器ID(左移12位)|sequence;// 序列号}}

移位规则:时间戳在最前面(高位),保证 ID 趋势递增——同一毫秒内先按数据中心、再按机器、最后按序列号排序。

时钟回拨:最大的坑

机器时间被 NTP 校准回退,或者运维手动改时间:

正常:t=1000 → 生成ID → t=1001 → 生成ID 回拨:t=1000 → 生成ID → t=999 → ??? 👈 时间倒退了! 后果: 1. 可能生成和之前重复的ID 2. lastTimestamp 逻辑混乱

解决方案

方案做法优缺点
直接报错检测回拨抛异常简单但影响可用性
等待追平小幅回拨等几毫秒适合偶发小幅回拨 👈
沿用上次时间回拨时用 lastTimestamp不报错但序列号可能溢出
预生成缓冲Leaf 双 Buffer 预生成不依赖实时时钟
// 美团 Leaf 的做法if(timestamp<lastTimestamp){longoffset=lastTimestamp-timestamp;if(offset<=5){// 小幅回拨,等一等 👈Thread.sleep(offset<<1);timestamp=System.currentTimeMillis();}else{// 大幅回拨,报错thrownewClockBackwardsException();}}

机器 ID 怎么分配

多台机器必须保证 workerId 不同:

方案做法缺点
配置文件每台机器写死扩展麻烦
ZK 分配启动时从 ZK 获取依赖 ZK
数据库分配启动时从 DB 获取依赖数据库
IP 取模IP hash % 32可能冲突
K8s Pod名哈希Pod 名称 hash % 32容器环境友好 👈
雪花算法全景 64位分配 ├── 1bit 符号位(永远0) ├── 41bit 时间戳(69年) ├── 5bit 数据中心(32个) ├── 5bit 机器ID(32台/数据中心) └── 12bit 序列号(4096个/毫秒) 生成流程 ├── 检测时钟回拨 ├── 同毫秒序列号递增 ├── 溢出则等下一毫秒 └── 移位拼装ID 核心风险 ├── 时钟回拨 → 等待/报错/预生成 └── 机器ID冲突 → ZK/DB/Hash分配 口诀:一位符号四十一时间,十个比特分机房; 十二序列每毫秒,四千零九十六个号; 时钟回拨要防范,小幅等待大幅报; 机器ID要唯一,ZK分配最可靠

回答技巧与点评

标准回答:雪花算法生成 64 位 ID:1 位符号(0)+ 41 位时间戳(毫秒,约 69 年)+ 5 位数据中心(32 个)+ 5 位机器 ID(32 台)+ 12 位序列号(4096 个/毫秒)。生成时先检测时钟回拨,同一毫秒内序列号递增,溢出则等下一毫秒,最后移位拼装。最大风险是时钟回拨,小幅回拨等几毫秒追平,大幅回拨则报错。

加分回答

  1. 美团的 Leaf-Snowflake:用 ZK 分配 workerId,同时双 Buffer 预生成 ID 放入环形数组,消费端直接取,不依赖实时时钟生成,彻底避免时钟回拨问题
  2. 百度 UidGenerator:用环形缓冲区(RingBuffer)预生成 ID,消费者直接从缓冲区取,单机 QPS 可达 600 万以上。时间戳的秒级精度改为毫秒级,位数分配更灵活
  3. 雪花 ID 的信息提取:从 ID 中可以反推出生成时间:(id >> 22) + epoch,这在排查问题时非常有用——从 ID 就能知道这条记录是何时创建的

面试官点评

这道题考的是你对分布式 ID 生成的实现细节。最忌讳的回答是只背 64 位分配——面试官想听的是生成流程(同毫秒序列号递增、溢出处理)和时钟回拨的解决。能写出生成代码的思路,再说出 Leaf 的优化,就是高分回答。

原文阅读


内容有帮助?点赞、收藏、关注三连!评论区等你 💪

http://www.jsqmd.com/news/983568/

相关文章:

  • QMCDecode:3步解锁QQ音乐加密音频,让音乐真正属于你
  • 2026永善律师行业洞察:口碑TOP10测评榜单揭晓 - 信息热点
  • zig语言学习笔记——Zig 的三大内存区域
  • 基于STM32F103C8T6的空气监测硬件套件,含微信小程序远程控制、OneNET云同步与OLED本地显示
  • AI 创意工具产品化:AI 图像生成的用户工作流设计
  • 小白程序员必备:收藏这份大模型学习指南,轻松入门AI新世界!
  • 3步解锁Wand专业版功能:免费获得完整游戏修改体验
  • 如何用UniExtract2一键解决500+格式解压难题:终极文件提取指南
  • 5分钟掌握SRWE:终极窗口分辨率管理神器,让屏幕效率翻倍
  • 2026天津自动变速箱维修CVT变速箱维修双离合变速箱维修变速箱阀体维修全维度数据对比:天津精捷四项断层领先 - 企业深度横评dyy6420
  • 3步解决华硕游戏本过热问题:G-Helper降压降温完全指南
  • 终极指南:5分钟彻底解决Windows VC++运行库缺失问题
  • 郴州本地回收标杆:郴奢汇万宝店引领 - 小仙贝贝
  • 跨界处理器i.MX RT1020:打破MCU与MPU边界的嵌入式开发实战
  • 用Python和DouZero算法,我让AI在QQ欢乐斗地主里‘打工’了一下午(附完整配置与避坑指南)
  • 【万字文档+源码】基于springboot+vue摄影师分享交流社区系统 -学习项目资料分享
  • 别再手动截图了!用MATLAB plot函数一键导出Simulink仿真波形(附字体美化技巧)
  • 深入解析恩智浦K20系列MCU:ARM Cortex-M4内核与工业级嵌入式设计实战
  • 专业GEO优化和自助优化区别
  • Wand-Enhancer:释放游戏修改器完整潜力的终极解决方案
  • AI穿搭教学哪家强?车内穿搭对标+平价配饰干货,这个宝藏博主值得关注 - 信息热点
  • 小程序毕设项目:基于Springboot的防诈骗管理系统小程序 (源码+文档,讲解、调试运行,定制等)
  • NXP Kinetis KL02超低功耗MCU实战:从Cortex-M0+架构到物联网节点设计
  • CUDA自学笔记01—Reduction规约求和
  • AI大模型时代已来!小白程序员收藏,抓住高薪新机遇
  • 深入解析ARM MCU外设时序:从I2C、SDHC到I2S的电气规格与工程实践
  • Qwen3.6-35B-A3B_最新代码模型vLLM高效部署
  • 如何用JPEXS Free Flash Decompiler轻松解密和编辑SWF文件:完整指南
  • 总结速度差14倍 从14分钟缩至1分钟2026实测分钟搞定知识视频总结这个实用技
  • ZXPInstaller:3分钟搞定Adobe插件安装的免费开源方案