我将拥有非常宽的 C* 表。为了防止它们变得太宽,我遇到了一个非常适合我的策略。它在此视频中进行了介绍。 明智地存储分区
这种策略的好处是不需要“查找表”(它很快),坏处是需要知道桶的最大数量并最终没有更多桶来使用(不可扩展)。我知道我的最大桶大小,所以我会试试这个。
通过从表的主键计算散列,这可以与其余的主键一起用作存储桶部分。
我想出了以下方法来确保(我认为?)哈希对于特定的主键总是相同的。
使用番石榴散列:
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 主键,结果应该始终相同吗?
- 我可以依靠上述方法来完成这项工作吗?
- 有没有更好的散列大字符串的解决方案,所以它们总是会为给定的字符串产生相同的结果?
- 我是否总是需要从字符串中进行哈希处理,或者是否有更好的方法来为 C* 主键执行此操作并始终产生相同的结果?
拜托,我不想讨论特定表的数据建模,我只想有一个存储桶策略。
编辑:
进一步阐述并提出了这一点,因此字符串的长度可以是任意的。你对这个有什么看法?
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);
}