Redis Cluster: その「美しき非決定性」とシャーディングの深淵
多くのエンジニアがRedis Clusterを「単なる分散KVS」として消費している。だが、真のアーキテクトであれば、それが単なるデータの断片化ではなく、「共有なきアーキテクチャ(Shared-Nothing Architecture)」における同期と非同期の高度なダンスであることを理解せねばならない。
本稿では、Redis Clusterの心臓部であるハッシュスロットのメカニズムから、その裏側で蠢くGossipプロトコルの実態までを解剖する。
—
1. 16384の魔法:CRC16とハッシュスロットの静的割り当て
Redis Clusterが16,384(2の14乗)という数値に固執する理由を知っているか?
これは単なる偶然ではない。ノード間のハートビートパケットにおいて、クラスタの構成状態(Bitmap)を効率的に伝播させるために計算された「最適解」だ。
- CRC16/XMODEM: キーの分散は`CRC16(key) mod 16384`で決定される。ここで重要なのは、キー全体ではなく `{}` で囲まれた「ハッシュタグ」のみを計算対象にする仕様だ。これにより、関連するキーを単一のシャードに物理的に配置(Locality)させることが可能になる。
- なぜ16,384か: 1,000ノード規模のクラスタを想定した際、ビットマップ形式で構成情報を送受信すると、各ノードの通信オーバーヘッドが許容範囲内に収まる絶妙なサイズがこれだった。ノード数を増やせばスロット数も増やすべきという意見もあるが、現状の仕様ではこれが「安定とパフォーマンスのバランス点」である。
—
2. Gossip Protocol:沈黙を許さないノード間の対話
Redis Clusterには、中央集権的な管理者は存在しない。各ノードは「Gossipプロトコル(MEET/PING/PONG)」を通じて、クラスタの全貌を確率的に把握する。
// Redisの内部コードを抽象化した概念的な構造体
struct clusterNode {
char name[CLUSTER_NAMELEN]; // ノードID
int flags; // MASTER, SLAVE, FAIL等
unsigned char slots[16384/8]; // このノードが担当するスロットのビットマップ
// …
};
このGossipの恐ろしい点は、「ある時点でのクラスタの全容は、誰にも完全には把握できていない」ということだ。ノードは定期的にランダムなノードを選択しPINGを送る。これにより、情報の伝播はエントロピー的に拡散する。これは、大規模システムにおける「完全な整合性」を諦め、「最終的な一貫性(Eventual Consistency)」を担保するための苦渋の選択であり、かつ極めて賢明な設計である。
—
3. リシャーディング:停止なき移行の物理的挙動
リシャーディング(`redis-cli –cluster reshard`)は、運用において最も神経を使うプロセスだ。この際、内部では何が起きているのか。
1. 遷移状態の生成: 移動対象のスロットに対して `MIGRATING` (ソース側) と `IMPORTING` (ターゲット側) というフラグが立つ。
2. キーの移動: `MIGRATE` コマンドが発行される。これは内部で `DUMP` と `RESTORE` をアトミックに実行する特殊なコマンドだ。
3. リダイレクトの連鎖: 移行中、キーがまだ移動していなければソースノードが応答するが、移動済みであればターゲットノードへの `ASK` リダイレクトをクライアントに返す。
注意すべきはメモリのスパイクだ。 `MIGRATE` 中はソースとターゲットの両方にデータが滞留する瞬間がある。メモリ使用率が限界に近いノードに対して強引にリシャーディングをかけることは、OOM Killerへの招待状を送るに等しい。
—
4. チーフアーキテクトからの提言:可用性の限界
最後に、Redis Clusterの「可用性」に対する幻想を砕いておく。
- Failoverの代償: `failover` が発生すると、クラスタは即座に停止する。Redis Clusterは「一貫性」を優先するため、ネットワーク分断が発生した際、マスターが不在となったパーティションは書き込みを受け付けない。
- クライアントの責務: `MOVED` や `ASK` リダイレクトをハンドリングできないクライアントは、Redis Clusterを使う資格がない。スマートクライアントは、常にノード間の構成変更をキャッチアップし、ローカルのハッシュスロットマップを更新し続ける必要がある。
結論
Redis Clusterは「銀の弾丸」ではない。
16,384のスロットを制御し、Gossipの揺らぎを理解し、メモリのフラグメンテーションと闘う。この泥臭い運用の先にしか、真のスケールアウトは存在しない。
アーキテクチャとは、「何を諦め、何を担保するか」の選択の歴史である。Redisを選んだのであれば、その「非決定的な分散環境」を愛し、コントロールする覚悟を持つことだ。
— 現場からは以上だ。コードを書き、メトリクスを読み、そしてシステムに耳を澄ませろ。
コメント