推文
@Zen_with_AI · 2026-10-17 08:03
小路带你60天学系统设计Day 20/60|分布式 ID 生成器:Snowflake 怎么做到全局唯一又有序? Day 19 的限流讲到"按用户 ID + 接口分桶"——分桶的前提是 ID 得靠谱。今天讲面试里 ID 绕不开的一题:几十台机器同时发号,怎么保证 ID 全局唯一,还按时间大致有序? 为什么不用 UUID?UUID v4 是 128 位随机数,唯一性够了,但无序——写进数据库 B+ 树,随机主键导致页分裂、写入性能崩。MySQL 自增主键有序,但单点、分库后撞号。分布式 ID 要同时满足四点:全局唯一、趋势递增(大致有序)、高可用、高性能(单机每秒几十万)。 Snowflake(Twitter 2010):64 位 ID,四段拼起来: 1 位符号位,固定 0 41 位时间戳(毫秒级,约 69 年寿命) 10 位机器 ID(5 位数据中心 + 5 位机器,可配) 12 位序列号(同一毫秒内计数,每毫秒 4096 个) 机器 ID 不同 → 机器间不撞;序列号 → 同机同毫秒不撞;时间戳在高位 → ID 随时间递增。时钟回拨是最大坑:机器时钟往回拨了,时间戳变小,可能撞上之前发过的 ID——常见做法是回拨就拒绝发号 / 等时钟追上来,小回拨可以等,大回拨直接报警停机。 面试官真正会钻的点: 41 位时间戳的起点:不用 Unix 纪元,用项目上线时间做 epoch,69 年才用完 机器 ID 怎么分配:写死配置最简单但扩容麻烦;ZooKeeper / etcd 动态分配,机器下线回收 ID 12 位序列号不够怎么办:同一毫秒超过 4096 个请求——要么等下一毫秒,要么把位数从时间戳 / 机器 ID 里挪 不要用数据库自增段:发号服务本身就是单点,挂了全停 美团 Leaf / 滴滴 TinyID 是另一条路:号段批量取号(一次取 1000 个号缓存在内存),性能更高,但号段用完要续,服务重启会跳号(不连续但唯一) 规模估算:41 位毫秒时间戳 + 12 位序列号 = 单机每秒约 409.6 万个 ID;1024 台机器理论上限约 42 亿/秒。瓶颈不在发号,在时钟——NTP 同步误差要控制在毫秒级。 💡 思考题:订单号要求"用户看不出来一天有多少单",全局唯一递增的 Snowflake ID 会暴露业务量——你会怎么改?(提示:打乱高位 / 加密映射 / 换号段) #系统设计60天
曝光 726 · 评论 2 · 点赞 1 · 书签 3 · 曝光/时 353.44672494070545