Twitter的雪花算法(Snowflake Algorithm)是一种由Twitter开发的生成唯一ID的方法。这一算法以其64位长整数形式的ID而闻名,确保了在分布式系统中ID的全球唯一性。
然而,在实际的业务应用中,我们有时会遇到对更短ID的需求。例如,在涉及嵌入式硬件的项目中,可能由于系统限制,需要使用48位的全局唯一ID。这时,对标准雪花算法进行适当的“魔改”便能有效地解决这一挑战。
那么,为什么在需要非8字节的唯一ID场景下,我们不直接选择使用递增数字呢?
关键在于,递增数字作为ID可能无意间暴露了业务的规模或其他敏感信息。使用雪花算法,不仅可以维持ID的唯一性,同时也更好地保护了业务的隐私和安全。
📝 Twitter的雪花算法
雪花算法是 Twitter 开发的,旨在解决在分布式系统中生成唯一、有序且高效的 ID 的具体挑战,用于 Twitter API 上可用的各种对象,包括推文、私信、用户和列表。
标准的雪花算法解决了在分布式系统中生成唯一标识符的问题。雪花算法的优势在于能够在不依赖数据库的情况下,生成全局唯一的ID,特别适用于高并发的场景。
这一算法将64位长整数划分为多个部分:
- 第1位占用1bit,其值始终是0,可看做是符号位不使用。
- 第2位开始的41位是时间戳,41-bit位可表示2^41个数,每个数代表毫秒,那么雪花算法可用的时间年限是
(1L<<41)/(1000L*3600*24*365)=69 年的时间。
- 中间的10-bit位可表示机器数,即2^10 = 1024台机器,但是一般情况下我们不会部署这么台机器。如果我们对IDC(互联网数据中心)有需求,还可以将 10-bit 分 5-bit 给 IDC,分5-bit给工作机器。这样就可以表示32个IDC,每个IDC下可以有32台机器,具体的划分可以根据自身需求定义。
- 最后12-bit位是自增序列,可表示2^12 = 4096个数。所以单机器一毫秒最多能生成4096个ID。
Twitter官方原版的雪花算法使用Scala编写,而Java版本也广泛应用。更多详情可参考官方GitHub链接。Java版本写法可以参考以下代码:
🤗 变种的雪花算法
在某些场景下,可能需要更短的ID,例如48位或32位。这时候可以对雪花算法进行修改。例如,可以减少时间戳的位数或序列号的位数,以适应更短的长度要求。这种变种的雪花算法仍然能保持ID的唯一性,但在时间跨度或最大并发量上可能会有所减少。
比如当前业务需要48位的唯一ID,则可以将原版雪花算法中的64位各部分做一个裁剪。
- 第1位开始的32位是秒级时间戳,可用的时间年限是
(1L<<32)/(3600*24*365)=136 年。
- 中间的4bit位可表示机器数,即最多2^4 = 16台机器。
- 最后12-bit位是自增序列,可表示2^12 = 4096个数。
单台机器的QPS4k,最多16台机器,大部分场景都是能胜任的。
使用类似的方法可以裁剪出53位(JavaScript支持的最大整型)或者32位(int类型)的雪花算法ID。
雪花算法依赖于机器时钟,当时钟回拨时可能导致ID重复。官方的处理是简单的抛出错误,但这可能造成服务在时间回拨期间不可用。针对不敏感于ID重复的业务,可以修改逻辑以提高服务可用性。此外,由于雪花算法需要保证机器ID或数据中心ID与机器ID的组合唯一性,在使用IP或MAC地址运算作为机器ID时需特别注意,尤其是在k8s等环境下,频繁重启或更换pod可能引发ID重复问题。
其他分布式ID生成方案有很多,各个大厂都有自己设计的方案,比如:
美团(Leaf)、滴滴(Tinyid)、百度(uid-generator)📎 参考文章
- 作者:Yibin
- 链接:https://yibin.dev/article/191d4969-482b-496b-87af-f49056c02d86
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章







