RedisをSentinel構成で運用しているときのSlaveノードの切り離し

RedisSentinelを使った構成で組んでいると、レプリケーションの制御をSentinelがよしなにやってくれるんだけど、あるSlaveノードを永久に切り離したいってなった時に、どうやるかって話。使っているバージョンは2.8系(下記のテストで利用したのは2.8.7。)
結局、ベストなやり方がわからないのだけど、以下のような感じで実施している。(いいやり方があれば教えてください。)

問題

通常、Redisでレプリケーションの解除は、

$ redis-cli slaveof no one

"SLAVEOF no one"コマンドを使うと良いのだけど、これだけだとSentinelが保持しているスレーブノードの情報は保たれたままなので、しばらくするとSentinel君が、レプリケーションが切れていることを検知して自動で再開してくれるような挙動になる。
なので、Sentinelからスレーブノードの情報を消さないといけないのだが、現バージョン(2.8.8時点)ではSentinelにそういったAPIが提供されていない(ように見える。ドキュメント的に)。

どうやったか

Sentinelが保持しているRedisマスタに紐付く情報をクリアする"SENTINEL reset"コマンドが用意されている。


なので、シーケンスとしては、

  • 特定のスレーブノードからのレプリケーションを解除する
    • マスタのinfo replicationから、該当するスレーブノードが消える
  • Sentinel全台に対して、"SENTINEL reset"コマンドを発行する
    • マスタに紐付く情報( known-slave がクリアされる)

こんな感じ。


レプリケーションの解除は"SLAVEOF no one"でもいいのだけど、割とすぐにSentinelが検知してリコネクト(レプリケーション再開)してくれちゃうので、思い切ってRedisプロセスを落としてしまうのが良さそう。


で、そのあと、"SENTINEL reset"コマンドを発行する。やり方は、

$ redis-cli -p 26379 sentinel reset mymaster

"mymaster"のところはmaster nameを指定してください。これをSentinel全台で実行します。
redis-cliでは"-h"オプションで、対象のホスト名やIPアドレスが指定できるので、ざっくざっく実行していきます。


これで、

$ redis-cli -p 26379 sentinel slaves mymaster

とか実行しても、スレーブノードが消えていることが確認できると思います。

SENTINEL reset

Sentinelのソースを読んでみると、resetの処理のところで以下コメントが確認できた。

/* Reset the state of a monitored master:
 * 1) Remove all slaves.
 * 2) Remove all sentinels.
 * 3) Remove most of the flags resulting from runtime operations.
 * 4) Reset timers to their default value.
 * 5) In the process of doing this undo the failover if in progress.
 * 6) Disconnect the connections with the master (will reconnect automatically).
 */

特定のmaster nameに紐付く、スレーブノードとSentinelノード、あと"flags resulting from runtime operations"の部分が、あまりよくわかっていないが、この辺がクリアされていそう。
尚、クリアされた後、再びマスタノードに情報を取得しに行く挙動だったけど、約2秒間隔でチェックしているみたいだった。

他のやり方

いったんSentinelを停止することが出来るのであれば、普通に設定ファイルから該当する"sentinel known-slave"の項目を削除して、Sentinelを起動しなおすことが確実かもしれない。
(アプリケーションなどのクライアントが、SentinelからRedisスレーブノードの情報を動的に引っ張っていたりすると、カジュアルに停止できないので、これが難しいこともある。)


もうちょっとエレガントなやり方はないのかなぁ、と疑問を残しておくと、誰かが教えてくれるかもしれないと淡い期待をいだきつつ、、、また何かわかったら書きます。

それでは! =͟͟͞͞(๑•̀=͟͟͞͞(๑•̀д•́=͟͟͞͞(๑•̀д•́๑)=͟͟͞͞(๑•̀д•́