从多部分主键生成C *桶哈希

时间:2016-10-22 09:05:50

标签: hash cassandra datastax-enterprise sha murmurhash

我将拥有非常广泛的C *表。为了防止它们变得太宽,我遇到了一个适合我的策略。它出现在这个视频中。 Bucket Your Partitions Wisely

这个策略的好处是不需要“查找表”(它很快),不好的部分是需要知道最大数量的桶并最终没有更多桶使用(不可扩展)。我知道我的最大铲斗尺寸所以我会尝试这个。

通过计算表主键的哈希值,可以将其与其他主键一起用作桶部分。

我想出了以下方法(我认为?)对于特定的主键,哈希总是相同的。

使用番石榴哈希:

public static String bucket(List<String> primKeyParts, int maxBuckets) {

    StringBuilder combinedHashString = new StringBuilder();
    primKeyParts.forEach(part ->{
        combinedHashString.append(
            String.valueOf(
                Hashing.consistentHash(Hashing.sha512()
                    .hashBytes(part.getBytes()), maxBuckets)
            )
        );
    });
    return combinedHashString.toString();
}

我使用sha512的原因是能够使用最大字符数为256(512位)的字符串,否则结果将永远不会相同(根据我的测试看来)。

我远不是一个哈希大师,所以我问下面的问题。

要求:在不同节点/机器上的不同JVM执行之间,对于给定的Cassandra主键,结果应始终相同?

  1. 我可以依靠上述方法来完成这项工作吗?
  2. 是否有更好的哈希大字符串解决方案,因此它们总是会为给定的字符串产生相同的结果?
  3. 我是否总是需要从字符串哈希或者是否有更好的方法为C *主键执行此操作并始终产生相同的结果?
  4. 拜托,我不想讨论特定表格的数据建模,我只想制定一个桶策略。

    修改

    进一步阐述并提出这个,所以字符串的长度可以是任意的。你怎么说这个?

    public static int murmur3_128_bucket(int maxBuckets, String... primKeyParts) {
    
        List<HashCode> hashCodes = new ArrayList();
        for(String part : primKeyParts) {
            hashCodes.add(Hashing.murmur3_128().hashString(part, StandardCharsets.UTF_8));
        };
        return Hashing.consistentHash(Hashing.combineOrdered(hashCodes), maxBuckets);
    }
    

1 个答案:

答案 0 :(得分:2)

我目前在生产中使用类似的解决方案。所以对于你的方法我会改为:

public static int bucket(List<String> primKeyParts, int maxBuckets) {
  String keyParts = String.join("", primKeyParts);
  return Hashing.consistentHash(
                     Hashing.murmur3_32().hashString(keyParts, Charsets.UTF_8),
                     maxBuckets);
}

所以差异

  1. 立即将所有PK部分发送到哈希函数中。
  2. 我们实际上将最大存储桶设置为代码常量,因为只有在最大存储桶保持不变的情况下才会保持一致的哈希值。
  3. 我们使用MurMur3哈希,因为我们希望它快速而不是加密强大。
  4. 您的直接问题1)是的,该方法应该完成这项工作。 2)我认为通过上面的调整你应该设置。 3)假设你需要整个PK吗?

    我不确定您是否需要使用整个主键,因为期望主键的分区部分对于许多内容都是相同的,这就是为什么要进行分组。您可以只是对可以为您提供好分区的位进行哈希处理,以便在分区键中使用。在我们的例子中,我们只是哈希PK的一些聚类关键部分,以生成我们用作分区键一部分的桶ID。