本文介绍了一个直接支持分布式标识符生成的实现。
1. 分布式系统中的并发标识符生成
每个主机都有一个预定义的唯一主机标识符或hostId 。
TimeProvider[url=https://github.com/OpenHFT/Chronicle-Core/blob/ea/src/main/java/net/openhft/chronicle/core/time/TimeProvider.java] [/url]提供了同时最多100 个主机生成不同的主机标识符。
2. 带有主机标识符的纳秒时间戳
DistributedUniqueTimeProvider将主机标识符存储在时间戳的低两位数字中,使其更易于阅读。
这使您可以在多达 100 台机器上生成有保证的唯一标识符。
同一台机器上的多个 JVM 共享一个 hostId。
时间戳在 hostId 为 28 的机器上看起来像这样:
2021-12-28T14:07:02.9541001 28 |
前面是时间:日期/时间/微秒
最后两位数字是主机标识符
这样更容易在时间戳中查看来源。
这提供了十分之一微秒(数百纳秒)的分辨率。 无论如何,这通常是许多系统中可用挂钟的限制。
默认情况下,可以在命令行上使用-DhostId= xx将hostId设置为系统属性,或者通过调用
DistributedUniqueTimeProvider.INSTANCE.hostId(hostId) ; |
使用主机标识符加速分配
通过预配置的主机标识符并跟踪共享内存中的最新标识符,能够实现跨机器快速并发生成标识符,达到每秒十亿的理论极限。
方法很简单:取当前时间,去掉低两位数字并添加hostId,只要这高于最后一个标识符,就可以了。
如果机器发生故障,最后一个标识符的信息丢失,假设重新启动服务的时间足以确保没有重叠。
如果服务失败了,但机器没有,信息就会被保留。
下面代码使用了开源库Chronicle Bytes支持的共享内存中的 MappedFile :
@Override |
使用 JMH测试:
On an i9-10980HK |
这种方法比UUID快6倍