3 votes

Générer un hachage de seau C* à partir d'une clé primaire multipartite

J'aurai des tables C* qui seront très larges. Pour éviter qu'ils ne deviennent trop larges, j'ai rencontré une stratégie qui pourrait bien me convenir. Elle est présentée dans cette vidéo. Mettez vos partitions à bon escient

L'avantage de cette stratégie est qu'elle ne nécessite pas de "look-up-table" (c'est rapide), l'inconvénient est qu'il faut connaître la quantité maximale de seaux et qu'on finit par ne plus avoir de seaux à utiliser (ce qui n'est pas évolutif). Je connais la taille maximale de mon seau, je vais donc essayer.

En calculant un hachage à partir des clés primaires de la table, on peut l'utiliser comme partie de seau avec le reste des clés primaires.

J'ai trouvé la méthode suivante pour être sûr (je pense ?) que le hash sera toujours le même pour une clé primaire spécifique.

Utilisation de Guava Hashing :

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();
}

La raison pour laquelle j'utilise sha512 est de pouvoir avoir des chaînes avec des caractères maximum de 256 (512 bit) sinon le résultat ne sera jamais le même (comme il semble d'après mes tests).

Je suis loin d'être un gourou du hachage, c'est pourquoi je pose les questions suivantes.

Exigence : Entre différentes exécutions de JVM sur différents nœuds/machines, le résultat devrait toujours être le même pour une clé primaire Cassandra donnée ?

  1. Puis-je compter sur la méthode mentionnée pour faire le travail ?
  2. Existe-t-il une meilleure solution pour hacher de grandes chaînes de caractères afin de produire toujours le même résultat pour une chaîne donnée ?
  3. Dois-je toujours effectuer un hachage à partir d'une chaîne de caractères ou existe-t-il une meilleure façon de procéder pour une clé primaire C* et produire toujours le même résultat ?

S'il vous plaît, je ne veux pas discuter de la modélisation des données pour une table spécifique, je veux juste avoir une stratégie de seau.

EDITAR:

J'ai poussé plus loin et j'ai trouvé ceci pour que la longueur de la corde puisse être arbitraire. Que dites-vous de celle-ci ?

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);
}

2voto

Jeff Beck Points 2495

J'utilise actuellement une solution similaire en production. Donc pour votre méthode, je changerais pour :

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);
}

Donc les différences

  1. Envoyez toutes les parties du PK dans la fonction de hachage en une seule fois.
  2. En fait, nous définissons les buckets max comme une constante de code puisque le hachage cohérent n'est possible que si les buckets max restent les mêmes.
  3. Nous utilisons le hachage MurMur3 car nous voulons qu'il soit rapide mais pas cryptographiquement fort.

Pour vos questions directes 1) Oui, la méthode devrait faire l'affaire. 2) Je pense qu'avec les ajustements ci-dessus, vous devriez être prêt. 3) L'hypothèse est que vous avez besoin de la PK entière ?

Je ne suis pas sûr que vous ayez besoin d'utiliser toute la clé primaire puisque l'on s'attend à ce que la partie partition de votre clé primaire soit la même pour beaucoup de choses, c'est pourquoi vous faites du bucketing. Vous pouvez simplement hacher les bits qui vous fourniront de bons buckets à utiliser dans votre clé de partition. Dans notre cas, nous hachons simplement certaines des parties de la clé de clustering de la PK pour générer l'identifiant du seau que nous utilisons comme partie de la clé de partition.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X