目前我正在尝试在客户端生成 long 类型的唯一标识符。 我有一个父/子关系,其中父已经有一个 UUID 作为标识符。 我想考虑使用 Parent-UUID 来计算 long 类型的 Child-Id。
我现在有这个实现:
public static void main(String[] args) {
/** Funnel. */
final Funnel<UUID> UUID_FUNNEL = new Funnel<UUID>() {
@Override
public void funnel(UUID parentUUID, PrimitiveSink into) {
final UUID tmpId = UUID.randomUUID();
into
// consider parent uuid
.putLong(parentUUID.getMostSignificantBits())
.putLong(parentUUID.getLeastSignificantBits())
// consider tmp uuid
.putLong(tmpId.getMostSignificantBits())
.putLong(tmpId.getLeastSignificantBits());
}
};
final UUID parentUUID = UUID.randomUUID();
System.out.println(parentUUID.toString());
for (int i = 0; i < 1000; i++) {
final long childId = Hashing.murmur3_128().newHasher()
.putObject(parentUUID, UUID_FUNNEL)
.hash().asLong();
System.out.println(childId);
}
}
您如何看待这个想法? 欢迎提出任何建议。
我已经读过这个问题: How to generate unique Long using UUID
最佳答案
这真的行不通。肯定不会比随机 long
更好。
- 没有
tmpId
:您只散列parentUUID
,因此同一父项的所有子项都得到相同的long
。 - 使用
tmpId
:您可以使用UUID.randomUUID().getLeastSignificantBits()
或仅使用random.nextLong()
并保存所有内容工作(散列随机值会导致随机结果,无论您添加什么)。
I have multple clients not only one.
然后询问一个独特的服务器。这包括一些可以使用 hi-lo algorithm 轻松最小化的开销。 .
At the DB level the child id's must be unique.
那就不管了,让DB生成id。每个数据库都有一些 AUTOINCREMENT 或 SEQUENCE 正是为此而设计的。
如果您在访问数据库之前需要客户端中的 ID,请询问数据库(并使用 hi-lo 算法以最大程度地减少开销)。
离线工作
我刚看到你的评论:
The clients should not go to a server to get the next id. It must be possible to work offline.
这是一个很大的痛苦。您可以做的任何散列都不会比随机 long
更好。
- 一组一百万个随机
long
的碰撞几率约为1e-6
,这可能是可以接受的。请注意,由于生日悖论,机会随集合大小二次增长。 - 您可以尝试在没有 ID(使用其他标识符)的情况下处理离线创建的实体,但这听起来很痛苦。
- 您可以为每个客户预分配一些 ID。这听起来很浪费,但为一百万个客户中的每一个预先分配 100 个 ID 使用的 ID 不到所有可能 ID 的 5%。
- 您可以切换到随机
UUID
。由于它们的长度为 128 位,因此即使对于数十亿个 ID,冲突机会也几乎为零。
关于java - 使用来自谷歌 Guava 的 Murmur3 生成长唯一 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41613540/