压测时 NTP 校时把机器时间往回拨了 12 毫秒,同一毫秒内生成的两批订单号有 47 个完全相同,插入时报 1062 Duplicate entry。乍看像缓存或者权限的锅,追下去往往不是。

if (now < lastTimestamp) {
  long offset = lastTimestamp - now;
  if (offset > 5) throw new IllegalStateException("clock moved backwards");
  waitUntil(lastTimestamp);
}

追下去是这么回事:Snowflake 的序列号只在同一毫秒内自增,时间回拨后毫秒数重复,序列号又从 0 开始,机器号相同时也无法区分。生成器里没有记录上次时间,回拨检测被跳过。

碰到「雪花算法时钟回拨」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。

线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。

具体做法是,在生成器里记录 lastTimestamp 发现回拨就等到追平;等待超过阈值直接抛异常 让上游换机器或换号段;序列号用满时阻塞到下一毫秒 不要直接进位;给订单号加唯一索引兜底 重复时重新生成。

验收就看一点,重复压测后订单号集合没有交集 插入不再报 1062。

作者 9823189