Hash 从多部分主键生成C*bucket散列

Hash 从多部分主键生成C*bucket散列,hash,cassandra,datastax-enterprise,sha,murmurhash,Hash,Cassandra,Datastax Enterprise,Sha,Murmurhash,我会有非常宽的C*表。为了防止它们变得太宽,我遇到了一个非常适合我的策略。这是在这段视频中介绍的。 这种策略的优点是不需要“查找表”(它很快),缺点是需要知道桶的最大数量,最终没有更多的桶可使用(不可伸缩)。我知道我的最大桶大小,所以我会试试这个 通过从表主键计算散列,可以将其与其余主键一起用作bucket部分 我提出了以下方法来确保(我想?)特定主键的哈希值总是相同的 使用番石榴哈希: public static String bucket(List<String> primKe

我会有非常宽的C*表。为了防止它们变得太宽,我遇到了一个非常适合我的策略。这是在这段视频中介绍的。

这种策略的优点是不需要“查找表”(它很快),缺点是需要知道桶的最大数量,最终没有更多的桶可使用(不可伸缩)。我知道我的最大桶大小,所以我会试试这个

通过从表主键计算散列,可以将其与其余主键一起用作bucket部分

我提出了以下方法来确保(我想?)特定主键的哈希值总是相同的

使用番石榴哈希:

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();
}
publicstaticstringbucket(列出primKeyParts、int-maxbucket){
StringBuilder combinedHashString=新StringBuilder();
primKeyParts.forEach(部件->{
combinedHashString.append(
String.valueOf(
Hashing.consistentHash(Hashing.sha512()
.hashBytes(part.getBytes()),maxBucket)
)
);
});
返回combinedHashString.toString();
}
我使用sha512的原因是能够拥有最大字符数为256(512位)的字符串,否则结果将永远不会相同(根据我的测试,结果似乎是一样的)

我远非散列大师,因此我提出以下问题

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

  • 我能依靠上面提到的方法来做这项工作吗
  • 是否有更好的解决方案对大字符串进行散列,以便它们总是为给定字符串生成相同的结果
  • 我是否总是需要从字符串散列,或者是否有更好的方法对C*主键执行此操作并始终生成相同的结果
  • 拜托,我不想讨论特定表的数据建模,我只想有一个bucket策略

    编辑:

    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();
    }
    
    对此进行了进一步的阐述,并得出了这样的结论:字符串的长度可以是任意的。你觉得这个怎么样

    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);
    }
    
    public static int-3\u 128\u bucket(int-maxbucket,String…primKeyParts){
    List hashcode=new ArrayList();
    用于(字符串部分:primKeyParts){
    add(Hashing.3_128().hashString(part,StandardCharsets.UTF_8));
    };
    返回Hashing.consistentHash(Hashing.combineOrdered(hashCodes),maxBucket);
    }
    
    我目前在生产中使用类似的解决方案。因此,对于您的方法,我将改为:

    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);
    }
    
    publicstaticintbucket(列出primKeyParts、intmaxbucket){
    String-keyParts=String.join(“,primKeyParts);
    返回Hashing.consistentHash(
    Hashing.3_32().hashString(keyParts,charset.UTF_8),
    最大桶数);
    }
    
    那么区别是什么呢

  • 一次将所有PK部分发送到哈希函数中
  • 实际上,我们将max bucket设置为一个代码常量,因为只有当max bucket保持不变时,才会使用一致散列
  • 我们使用杂音3散列,因为我们希望它是快速的,而不是加密强大的
  • 对于您的直接问题1)是的,该方法应该可以完成任务。2) 我认为通过上面的调整,你应该被设置好。3) 假设你需要整个PK


    我不确定您是否需要使用整个主键,因为我们期望您的主键的分区部分在很多情况下都是相同的,这就是为什么您要使用bucketing。您只需散列将为您提供在分区密钥中使用的好桶的位。在我们的例子中,我们只是散列PK的一些集群键部分,以生成我们用作分区键一部分的bucket id。

    我正要用更好的解决方案编辑我的“问题”,它非常相似,点击enter。。。看看我的更新,告诉我你的想法。顺便说一句,很好的答案。。给我更多的信心!我不知道你为什么要单独散列每个部分,然后做一致的散列。到目前为止,只需对附加部分进行散列就可以了。我认为第三条路应该走。你应该复习一下我上面关于使用所有PK的注释。就可以了!谢谢杰夫。。。(你的大名):)