Snowflake IDs 或 snowflakes 是一种应用于分布式系统的 id 形式,由 Twitter 创造并用于标记其内容 (tweets). Discard, Instagram 等互联网公司也采用了修改后的雪花id。
(wikipedia 对 Snowflake ID 的说明)
原理说明
雪花id的原理非常简单。一个 long
占用 64 digits, 将之划分成四个区段,分别存放不同的信息:
区段一
长度为 1 digit 且固定为 0,用于兼容无法使用 unsigned long
的语言(如 Java), 否则 id 会显示成负数。
区段二 - timestamp
长度为 41 digits, 用于记录时间戳 timestamp。需要注意的是,该时间戳的起点不是通常的 1970-01-01
,而是自定义的某个时间点。
例如:设置时间起点为 2010-01-01 00:00:00:0
,则 timestamp=1000
时,对应的时间点为 2010-01-01 00:00:01:0
。
使用 41 digits, 可表示约 69 年,即基于起点时间的 69 年以内可用:
1 | // 验证 41 digits 的最大值为多少年 |
区段三 - instance
10 digits 用于表示实例的编号或索引值,即可用于区分 2^10 = 1024 个雪花id生成器的实例。理论上可部署多台服务器、每台服务器存在多个实例,只要总数在 1024 以内即可,这也是 Snowflake ID 支持分布式系统的关键。
网络上有些资料把 instance 区段再拆分开 datacenter 和 worker,实际上原理都是一样的,就不展开了。
区段四 - sequence
12 digits 用于表示序列号,且与 timestamp 相应。即理论上同一毫秒内,可生成 2^12 = 4096 个 sequence. (如果超出该数量,则等待直到下一毫秒)
缺点
个人认为最大缺点应该是不能直接反映生成日期。在业务上,将日期反映在订单编号上,对于运维来说应该是比较便利的。
定制版
基于以上原理,其他人均可修改区间定义以实现自己的定制版。例如:
- 把首个 digit 也加入有意义的区间
- 增加或减少 instance 的区间长度
- 缩减部分区间长度,用于自定义的区间,如版本号、业务模块索引等
代码示例
参考了网络资料,并作出部分优化、完善注释。
1 | public class SnowflakeId { |