LoginSignup
0
0

Redisのクラスターモードで、mgetコマンドを使用してキーの一括値を取得する際の問題の解決策について説明します

Posted at

Redisのクラスターモードにおいて、mgetコマンドを使用して複数のキーに対応する値のセットを一括で取得する必要がありましたが、値の取得時に次のエラーが発生しました:"ERR CROSSSLOT Keys in request don't hash to the same slot"。これを日本語に翻訳すると、「リクエスト内のこれらのキーは同じスロットにハッシュされていません」という意味です。つまり、Redisのクラスターモードでは、ハッシュ分割が行われるため、データを挿入するたびにRedisは自動的に各データが属するスロットを計算します。また、各スロットが異なるノードに存在する可能性もあるため、mgetを使用する際には、このバッチのキーが異なるノードに存在する場合に値を取得できなくなります。

Redisがデータのスロット位置を計算するアルゴリズムに基づいて考えると(原文はこちら)、次のようなコードが使われます。

unsigned int HASH_SLOT(char *key, int keylen) {
    int s, e; /* start-end indexes of { and } */

    /* Search the first occurrence of '{'. */
    for (s = 0; s < keylen; s++)
        if (key[s] == '{') break;

    /* No '{' ? Hash the whole key. This is the base case. */
    if (s == keylen) return crc16(key,keylen) & 16383;

    /* '{' found? Check if we have the corresponding '}'. */
    for (e = s+1; e < keylen; e++)
        if (key[e] == '}') break;

    /* No '}' or nothing between {} ? Hash the whole key. */
    if (e == keylen || e == s+1) return crc16(key,keylen) & 16383;

    /* If we are here there is both a { and a } on its right. Hash
     * what is in the middle between { and }. */
    return crc16(key+s+1,e-s-1) & 16383;
}

簡単に言うと、もしキーに{}の文字が含まれている場合、{}に含まれる文字だけがハッシュ計算に使用されます("{abc}.123"の場合、abcだけがハッシュ計算に使用されます)。また、最初の{}の組に含まれる内容だけがハッシュ計算に使用されるため、Redisクラスター内の特定のグループのデータを同じノードに格納する場合は、同じキーのプレフィックスを指定するだけで問題が解決します。例えば、"{abc}.123"、"{abc}.456"、"{abc}.789"はすべて同じノードに保存されるため、これによってmgetを使用して値を一括取得する際の問題が解決されます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0