状況
Redisインスタンスに対してCLUSTER INFOやCLUSTER NODESを実行したとき — デバッグ中、クラスター状態の確認、またはマイグレーションスクリプトの実行中など — 以下のエラーが表示されることがあります:
(error) ERR This instance has cluster support disabled
アプリやスクリプトが壊れてしまいます。厄介なのは、コマンド自体は完全に有効なRedisの構文であるという点です。Redisがそれを拒否するのは、このインスタンスでクラスターモードが有効化されていないからに過ぎません。
発生原因
Redisはスタンドアロンとクラスターの2つのモードのいずれかで動作します。すべてのインスタンスはデフォルトでスタンドアロンになります。そのモードでは、CLUSTER *コマンドはすべてプロトコルレベルで拒否されます — 実行を試みることなく、即座にエラーが返されます。
よくある原因のパターンをいくつか挙げます:
- 起動時にトポロジーを検出するために
CLUSTER INFOを自動実行するライブラリ — Lettuce、ioredis、Jedisはいずれもクラスタークライアントで初期化するとこの動作をします - クラスター環境向けに書かれたマイグレーションやデプロイスクリプトを、開発・ステージング環境のスタンドアロンRedisに誤って実行した
- クラスター対応クライアントが誤ったホストを向いている — 7000番台のクラスターエンドポイントではなく、6379番のスタンドアロンを指している
- デバッグ中に
CLUSTER MYIDやCLUSTER SLOTSを手動実行した
簡易診断
Redisが実際にどのモードで動作しているか確認します:
redis-cli -h 127.0.0.1 -p 6379 INFO server | grep redis_mode
以下のいずれかが返されます:
redis_mode:standalone
# または
redis_mode:cluster
standaloneと表示された場合、それが原因です。このインスタンスではクラスターコマンドは一切動作しません。
設定値も合わせて確認しておきましょう:
redis-cli CONFIG GET cluster-enabled
1) "cluster-enabled"
2) "no"
修正1:スタンドアロンが必要な場合 — クライアントを修正する
Redisが意図的にスタンドアロン(シングルノード、シャーディングなし)で動作している場合、問題はRedisではなく、間違ったコマンドを送っているクライアント側にあります。クラスタークライアントを通常のクライアントに切り替えましょう。
ioredis (Node.js) — new Redis(...)を使うべきところでnew Redis.Cluster([...])を使っている場合:
// 誤り — スタンドアロンRedisに対してクラスタークライアントを使用
const redis = new Redis.Cluster([
{ host: '127.0.0.1', port: 6379 }
]);
// 正しい — スタンドアロンクライアント
const redis = new Redis({
host: '127.0.0.1',
port: 6379
});
Jedis (Java) — JedisClusterをJedisPoolに置き換えます:
// 誤り
JedisCluster jedis = new JedisCluster(new HostAndPort("127.0.0.1", 6379));
// 正しい
JedisPool pool = new JedisPool("127.0.0.1", 6379);
Jedis jedis = pool.getResource();
Lettuce (Java/Spring) — RedisClusterClientの代わりにRedisClientを使います:
// 誤り
RedisClusterClient clusterClient = RedisClusterClient.create("redis://127.0.0.1:6379");
// 正しい
RedisClient client = RedisClient.create("redis://127.0.0.1:6379");
redis-py (Python):
# 誤り
from redis.cluster import RedisCluster
r = RedisCluster(host='127.0.0.1', port=6379)
# 正しい
import redis
r = redis.Redis(host='127.0.0.1', port=6379)
修正2:クラスターモードが必要な場合 — Redisの設定で有効化する
本当にクラスタリングが必要ですか?データのシャーディング、水平スケーリング、ノード間の高可用性が必要な場合は、redis.confでクラスターモードを有効化し、クラスターを適切に構築する必要があります。
ステップ1 — /etc/redis/redis.confを編集します:
# クラスターモードを有効化
cluster-enabled yes
# 各ノードは独自の状態ファイルが必要です — インスタンス間で共有しないでください
cluster-config-file nodes.conf
# ノードが到達不能とみなされるまでの時間(ミリ秒)
cluster-node-timeout 5000
ステップ2 — Redisを再起動します:
sudo systemctl restart redis
# または
redis-server /etc/redis/redis.conf
ステップ3 — Redisのクラスター形成には最低3つのマスターノードが必要です。7000〜7002番ポートで3つのインスタンスが起動している状態で:
redis-cli --cluster create \
127.0.0.1:7000 \
127.0.0.1:7001 \
127.0.0.1:7002 \
--cluster-replicas 0
プロンプトでyesと入力し、3ノードへのスロット割り当てを確認します。
修正3:エンドポイントの誤り — ポートを確認する
スタンドアロンとクラスターの両方のRedisを実行している場合、クラスタークライアントが誤って6379番ポートを向いてしまうことがあります。実際に何がリッスンしているか確認しましょう:
# リッスン中のポートを確認
ss -tlnp | grep redis
# または
netstat -tlnp | grep redis
tcp LISTEN 0 128 0.0.0.0:6379 # スタンドアロン
tcp LISTEN 0 128 0.0.0.0:7000 # クラスターノード1
tcp LISTEN 0 128 0.0.0.0:7001 # クラスターノード2
tcp LISTEN 0 128 0.0.0.0:7002 # クラスターノード3
クラスタークライアントは6379ではなく、クラスター用ポート(7000番台)を向ける必要があります。
修正の確認
スタンドアロンクライアントに切り替えた場合、基本的な読み書きを実行してクラスターエラーが出ないことを確認します:
redis-cli SET test_key "hello"
redis-cli GET test_key
# 期待される結果: "hello"
クラスターモードを有効化した場合、実際のトラフィックを流す前にクラスターが正常な状態であることを確認します:
redis-cli -p 7000 CLUSTER INFO | grep cluster_state
# 期待される結果: cluster_state:ok
redis-cli -p 7000 CLUSTER NODES
# 期待される結果: 3行、それぞれノードIDとスロット範囲(0-5460、5461-10922、10923-16383)が表示される
redis-cli -c -p 7000 SET foo bar
redis-cli -c -p 7000 GET foo
# -c フラグはredis-cliがMOVEDリダイレクトを自動的に追跡するよう指示します
注意:クラスターモードを有効化するとデータが消える
稼働中のスタンドアロンインスタンスをデータを消去せずにクラスターモードへ切り替えることはできません。Redisは各モードで異なる方法でデータを保存しており、インプレースでのマイグレーションは不可能です。
切り替える前に、必ずすべてのデータをダンプしておきましょう:
redis-cli --rdb dump.rdb
その後、新しいクラスターが起動したらデータをリストアします。このステップを省略すると、スタンドアロンインスタンスに保存されていたデータはすべて失われます。

