怃膝镁 发表于 2026-1-6 13:30:03

用雪花算法就不会产生重复的ID?

前言

今天想和大家聊聊分布式系统中常用的雪花算法(Snowflake)——这个看似完美的ID生成方案,实际上暗藏玄机。
有些小伙伴在工作中一提到分布式ID,第一个想到的就是雪花算法。
确实,它简单、高效、趋势递增,但你知道吗?
雪花算法的隐蔽的坑不少。
今天这篇文章跟大家一起聊聊雪花算法的5大坑,希望对你会有所帮助。
一、雪花算法:美丽的陷阱

先简单回顾一下雪花算法的结构。
标准的雪花算法ID由64位组成:
// 典型的雪花算法结构
public class SnowflakeId {
    // 64位ID结构
    // 1位符号位(始终为0) +
    // 41位时间戳(毫秒级) +
    // 10位机器ID +
    // 12位序列号
   
    private long timestampBits = 41;// 时间戳占41位
    private long workerIdBits = 10;   // 机器ID占10位
    private long sequenceBits = 12;   // 序列号占12位
   
    // 最大支持值
    private long maxWorkerId = -1L ^ (-1L << workerIdBits);// 1023
    private long maxSequence = -1L ^ (-1L << sequenceBits);// 4095
   
    // 偏移量
    private long timestampShift = sequenceBits + workerIdBits;// 22
    private long workerIdShift = sequenceBits;                  // 12
}跨语言兼容性测试表

语言/环境最大安全整数处理方案示例JavaScript2^53 (9e15)字符串化"12345678901234567"Python无限制直接使用12345678901234567Java2^63-1直接使用12345678901234567LMySQL BIGINT2^63-1直接存储12345678901234567JSON传输2^53大数转字符串{"id": "12345678901234567"}总结

1. 时钟问题:必须处理的现实

最佳实践:
<ul>使用waitNextMillis处理小范围回拨( 0.8) {            log.warn("序列号使用率过高: {}%", usageRate * 100);            alertService.sendAlert("SNOWFLAKE_HIGH_USAGE",               "序列号使用率: " + usageRate);                        // 自动扩容:调整时间戳粒度            if (usageRate > 0.9) {                upgradeToMicrosecond();            }      }    }}4. 时间戳溢出:早做规划

最佳实践:

[*]选择合理的起始时间(如项目启动时间)
[*]定期检查剩余时间
[*]准备升级方案(如扩展位数)
// 有问题的雪花算法实现
public synchronized long nextId() {
    long currentTimestamp = timeGen();
   
    // 问题代码:如果发现时钟回拨,直接抛异常
    if (currentTimestamp < lastTimestamp) {
      throw new RuntimeException("时钟回拨异常");
    }
   
    // ... 生成ID的逻辑
}5. 跨系统兼容:设计时就考虑

最佳实践:

[*]ID对象包含多种表示形式
[*]API响应统一使用字符串ID
[*]提供ID转换工具类
public class SnowflakeIdWorker {
    private long lastTimestamp = -1L;
    private long sequence = 0L;
   
    public synchronized long nextId() {
      long timestamp = timeGen();
      
      // 处理时钟回拨
      if (timestamp < lastTimestamp) {
            long offset = lastTimestamp - timestamp;
            
            // 如果回拨时间较小(比如5毫秒内),等待
            if (offset <= 5) {
                try {
                  wait(offset << 1);// 等待两倍时间
                  timestamp = timeGen();
                  if (timestamp < lastTimestamp) {
                        throw new RuntimeException("时钟回拨过大");
                  }
                } catch (InterruptedException e) {
                  Thread.currentThread().interrupt();
                  throw new RuntimeException("等待时钟同步被中断");
                }
            } else {
                // 回拨过大,抛出异常
                throw new RuntimeException("时钟回拨过大: " + offset + "ms");
            }
      }
      
      // 正常生成ID的逻辑
      if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & maxSequence;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
      } else {
            sequence = 0L;
      }
      
      lastTimestamp = timestamp;
      
      return ((timestamp - twepoch) << timestampShift) |
                (workerId << workerIdShift) |
                sequence;
    }
   
    // 等待下一个毫秒
    private long tilNextMillis(long lastTimestamp) {
      long timestamp = timeGen();
      while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
      }
      return timestamp;
    }
}最后的建议

雪花算法虽然优雅,但它不是银弹。
在选择ID生成方案时,需要考虑:

[*]业务规模:小系统用UUID更简单,大系统才需要雪花算法
[*]团队能力:能处理好时钟回拨等复杂问题吗?
[*]未来规划:系统要运行多少年?需要迁移方案吗?
如果决定使用雪花算法,建议:

[*]使用成熟的开源实现(如Twitter的官方版)
[*]完善监控和告警
[*]准备降级和迁移方案
记住:技术选型不是寻找完美方案,而是管理复杂度的艺术。
雪花算法有坑,但只要我们知道坑在哪里,就能安全地跨过去。
如果你在雪花算法使用中遇到其他问题,欢迎留言讨论。
最后说一句(求关注,别白嫖我)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。
求一键三连:点赞、转发、在看。
关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的10万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。
更多项目实战在我的技术网站:http://www.susan.net.cn/project

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

啪炽 发表于 2026-1-15 08:42:26

感谢发布原创作品,程序园因你更精彩

司马黛 发表于 2026-1-20 16:27:26

喜欢鼓捣这些软件,现在用得少,谢谢分享!

敖可 发表于 2026-1-21 19:25:13

过来提前占个楼

饨篦 发表于 2026-1-22 03:27:12

这个有用。

懵崭 发表于 2026-1-24 04:25:09

感谢分享

仟仞 发表于 2026-1-24 09:26:36

收藏一下   不知道什么时候能用到

鞣谘坡 发表于 2026-1-28 00:57:00

分享、互助 让互联网精神温暖你我

都淑贞 发表于 2026-1-30 04:02:07

热心回复!

陆菊 发表于 2026-2-4 11:44:34

感谢发布原创作品,程序园因你更精彩

后雪闵 发表于 2026-2-4 22:27:52

前排留名,哈哈哈

肿圬后 发表于 2026-2-6 07:28:18

感谢发布原创作品,程序园因你更精彩

荡俊屯 发表于 2026-2-6 12:57:11

很好很强大我过来先占个楼 待编辑

愆蟠唉 发表于 2026-2-8 00:53:43

感谢分享,学习下。

玛凶 发表于 2026-2-8 15:11:06

感谢分享

溧久苟 发表于 2026-2-8 18:52:42

这个好,看起来很实用

涣爹卮 发表于 2026-2-9 06:10:31

yyds。多谢分享

痕厄 发表于 2026-2-9 08:39:30

谢谢分享,试用一下

浦乐 发表于 2026-2-9 18:44:24

谢谢楼主提供!

兼罔 发表于 2026-2-9 22:23:10

收藏一下   不知道什么时候能用到
页: [1] 2
查看完整版本: 用雪花算法就不会产生重复的ID?