palaflake
snowflake改进型分布式ID生成方案
概述
palaflake为低分布式场景提供全局唯一的ID生成方案,并通过时间回拨位为更多场景提供冗余可能。
ID结构
palaflake同snowflake一样,采用64个二进制位来生成ID,palaflake也是一个i64值。
下面是一个标准的palaflake二进制表示(间隔和换行是出于排版考虑):
01112222 22222222 22222222 22222222
22222222 22223333 33334444 44444444
-
首位(被标识为0):弃用,置0,因为有符号64位整数在大多数应用场景中更为通用。
-
第2~4位(共3位,被标识为1):时间回拨位,允许至多承受7次时间回拨。
-
第5~44位(共40位,被标识为1):精确到毫秒的时间戳,其最大使用年限为34年。
-
第45~52位(共8位,被标识为3):实例标识,最大可供256个实例同时生成ID。
-
第53~64位(共12位,被标识为4):序列号,支持每毫秒生成4096个ID。
最佳实践
为充分利用ID空间,请使用从项目启动时间开始的毫秒级时间戳。
palaflake默认支持高达每秒400万(4096000)的并发量,可通过降低第5~44位的时间戳的精确程度来降低palaflake的并发程度以更加充分地利用ID空间(例如每10毫秒增加一次时间戳)。
注意事项
-
对于单一实例,palaflake能够保证系统在线期间每次都产生递增的ID,但不能保证系统重启后产生的ID相较于重启前是递增的(这是因为存在时间回拨位,如果不触发时间回拨,那么仍能保证重启后ID的递增性)。
-
对于多实例,palaflake仅能保证ID的全局唯一性,不能保证多实例间ID的递增性。
-
palaflake的时间回拨位允许系统至多发生7次时间回拨,在这期间依然能够产生唯一且递增的ID,应该在触发时间回拨后将后续ID映射到安全的ID空间,并置0回拨位。
实现
均包含一份示例代码和一个可直接编译使用的Library。
使用方法:
//以Kotlin为例,其他语言大同小异。
import Palaflake.Generator
fun main() {
val g = Generator(1, 2022u)//实例标识和计时起始年
println(g.next())
}
已知问题
- 仅对于Windows10测试环境下的Kotlin实现,在以极高速度生成ID时有概率发生时间回拨位的过多递增(在单线程下也是如此),此问题并不影响生成ID的唯一性与递增性,但会使得容许的时间回拨次数减少。目前在实现中通过引入额外阻塞来限制ID生成速度以屏蔽此问题,但仍不能确定该问题是否会在其他情况下复现,详见Kotlin实现中的
//TODO
标记。其他语言的实现版本并无此问题。另对于macOS12测试环境下,此问题未复现。
版本历史
v1.1.0
去除了保留位,因其意义不明且浪费ID空间。 弃用了首位,以适应更多应用场景。 拓宽了时间回拨位,以容许更多回拨的发生。 提前了时间回拨位和时间戳位,以提高某些场景中对ID的索引性能。
v1.0.0
init