snowflake 改进型分布式ID生成方案
palaflake 为低分布式场景提供全局唯一的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())
}
- 仅对于 Windows 10 测试环境下的 Kotlin 实现,在以极高速度生成ID时有概率发生时间回拨位的过多递增(在单线程下也是如此),此问题并不影响生成 ID 的唯一性与递增性,但会使得容许的时间回拨次数减少。目前在实现中通过引入额外阻塞来限制 ID 生成速度以屏蔽此问题,但仍不能确定该问题是否会在其他情况下复现,详见 Kotlin 实现中的
//TODO
标记。其他语言的实现版本并无此问题。另对于 macOS 12 测试环境下,此问题未复现。
去除了保留位,因其意义不明且浪费ID空间。
弃用了首位,以适应更多应用场景。
拓宽了时间回拨位,以容许更多回拨的发生。
提前了时间回拨位和时间戳位,以提高某些场景中对ID的索引性能。