找回密码
 立即注册
首页 业界区 业界 用雪花算法就不会产生重复的ID?

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

怃膝镁 3 天前
前言

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

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

语言/环境最大安全整数处理方案示例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();            }        }    }}[/code]4. 时间戳溢出:早做规划

最佳实践

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

最佳实践

  • ID对象包含多种表示形式
  • API响应统一使用字符串ID
  • 提供ID转换工具类
  1. public class SnowflakeIdWorker {
  2.     private long lastTimestamp = -1L;
  3.     private long sequence = 0L;
  4.    
  5.     public synchronized long nextId() {
  6.         long timestamp = timeGen();
  7.         
  8.         // 处理时钟回拨
  9.         if (timestamp < lastTimestamp) {
  10.             long offset = lastTimestamp - timestamp;
  11.             
  12.             // 如果回拨时间较小(比如5毫秒内),等待
  13.             if (offset <= 5) {
  14.                 try {
  15.                     wait(offset << 1);  // 等待两倍时间
  16.                     timestamp = timeGen();
  17.                     if (timestamp < lastTimestamp) {
  18.                         throw new RuntimeException("时钟回拨过大");
  19.                     }
  20.                 } catch (InterruptedException e) {
  21.                     Thread.currentThread().interrupt();
  22.                     throw new RuntimeException("等待时钟同步被中断");
  23.                 }
  24.             } else {
  25.                 // 回拨过大,抛出异常
  26.                 throw new RuntimeException("时钟回拨过大: " + offset + "ms");
  27.             }
  28.         }
  29.         
  30.         // 正常生成ID的逻辑
  31.         if (lastTimestamp == timestamp) {
  32.             sequence = (sequence + 1) & maxSequence;
  33.             if (sequence == 0) {
  34.                 timestamp = tilNextMillis(lastTimestamp);
  35.             }
  36.         } else {
  37.             sequence = 0L;
  38.         }
  39.         
  40.         lastTimestamp = timestamp;
  41.         
  42.         return ((timestamp - twepoch) << timestampShift) |
  43.                 (workerId << workerIdShift) |
  44.                 sequence;
  45.     }
  46.    
  47.     // 等待下一个毫秒
  48.     private long tilNextMillis(long lastTimestamp) {
  49.         long timestamp = timeGen();
  50.         while (timestamp <= lastTimestamp) {
  51.             timestamp = timeGen();
  52.         }
  53.         return timestamp;
  54.     }
  55. }
复制代码
最后的建议

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

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

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

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

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

相关推荐

您需要登录后才可以回帖 登录 | 立即注册