雪花算法遇上时钟回拨,我们布了三道防线
【摘要】 雪花ID的结构:64位等于1位符号加41位毫秒时间戳加10位机器位加12位序列,单机每毫秒4096个,够绝大多数场景。它的命门是强依赖时钟单调——NTP校时把时钟拨回几十毫秒,同一毫秒内序列重用,ID就撞了。生产上真遇过:虚拟机宿主机时间漂移,NTP一次回拨37ms,上游开始报主键冲突。处理代码的三道防线:longnow=System.currentTimeMillis();if(now&l...
雪花 ID 的结构:64 位等于 1 位符号加 41 位毫秒时间戳加 10 位机器位加 12 位序列,单机每毫秒 4096 个,够绝大多数场景。它的命门是强依赖时钟单调——NTP 校时把时钟拨回几十毫秒,同一毫秒内序列重用,ID 就撞了。
生产上真遇过:虚拟机宿主机时间漂移,NTP 一次回拨 37ms,上游开始报主键冲突。处理代码的三道防线:
long now = System.currentTimeMillis();
if (now < lastTimestamp) {
long offset = lastTimestamp - now;
if (offset <= 5) {
// 小回拨:自旋等待时钟追上
LockSupport.parkNanos(offset * 100_000L);
now = System.currentTimeMillis();
} else {
// 大回拨:拒服务并告警,人工介入
throw new ClockBackwardsException(
"offset=" + offset + "ms");
}
}
第一道,回拨小于 5ms 自旋等待;第二道,大于 5ms 拒绝发号并告警,宁可短暂不可用也不发重复 ID;第三道在部署层:机器统一用 chrony 做平滑校时(slew 渐进模式,禁止 step 跳变),从源头减少回拨。
彻底不依赖时钟的替代方案也评估过:号段模式(美团 Leaf-segment,DB 批量发号)吞吐低一档但与时间解耦;Redis 自增简单但有持久化窗口的重复风险。我们的定版是核心交易用雪花加三道防线,边缘业务用号段,各自安心。发号器这种基础组件,出问题的瞬间影响面是全业务,防线宁多勿少。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)