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を使用して値を一括取得する際の問題が解決されます。