1

目前我正在尝试在客户端生成 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

4

1 回答 1

3

这真的行不通。肯定不比随机的好long

  • 没有tmpId:你只散列parentUUID,所以同一个父母的所有孩子都一样long
  • With tmpId:您可以使用UUID.randomUUID().getLeastSignificantBits()或只是random.nextLong()保存所有工作(散列随机值会导致随机结果,无论您添加什么)。

我有多个客户,而不仅仅是一个。

然后问一个独特的服务器。这包括一些开销,可以使用hi-lo 算法轻松最小化。

在数据库级别,子 ID 必须是唯一的。

那就算了,让DB生成id吧。每个数据库都有一些专门用于此目的的 AUTOINCREMENT 或 SEQUENCE。

如果您在访问数据库之前需要客户端中的 id,请询问数据库(并使用 hi-lo 算法以最小化开销)。

离线工作

我刚看到你的评论:

客户端不应去服务器获取下一个 ID。必须可以离线工作。

这是一个很大的痛苦。你能做的任何散列都不会比随机的好long

  • 一组一百万个随机longs 的碰撞机会约为1e-6,这可能是可以接受的。请注意,由于生日悖论,机会随设定大小呈二次方增长。
  • 您可以尝试在没有 ID 的情况下处理离线创建的实体(使用其他标识符),但这听起来很痛苦。
  • 您可以为每个客户端预先分配一些 ID。这听起来很浪费,但为 100 万个客户端中的每一个预分配 100 个 ID,所用的 ID 不到所有可能 ID 的 5%。
  • 您可以切换到 random UUIDs。由于它们的长度为 128 位,因此即使对于数十亿个 ID,碰撞几率也几乎为零。
于 2017-01-13T17:50:39.230 回答