redisのチューニング周りとレプリケーション2 | よしやのブログ

よしやのブログ

ブログの説明を入力します。

さて、皆さん、長らく放置してたredisのクラスタリングについて少し見ていきたいと思います。

ここでいうクラスタリングはレプリケーションをさします。シャーディングは少し難しい話に
なるのでまたの機会に先送りにしましょう。

1 構築方法

まずやってみるのか一番なので構築方法を書きます。
redisのプロセスを二つ立ち上げましょう。今日もリソースの問題で、全てローカルで作業しますが、その気になればネットワーク越しに作業することも容易のはず。(host portをそれぞれの環境に合わせて設定しましょう。)

$ redis-server --port 6379
これでまず、redis-serverが起動しました。待ち受けのポーとは6379番です。ちなみにredisはデフォルトで6379に待機するのでこのオプションは無くてかまいませんが、今回スレーブも同時にローカルに立てるので明示的に書きました。

次に別のshellを開いて
$ redis-server --port 6380
これでもう一つredisのプロセスが立ち上がりました。試しに更に別のshellで ps aux | grep redis
とかやるとプロセスが二ついます。

次に、redis-cliでスレーブにしたい方にアクセスして見ましょう。
$ redis-cli -p 6380
redis 127.0.0.1:6380>

こんなプロンプトが出ます。次に、これをスレーブにするためにコマンドを一つ打ちます。

redis 127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
redis 127.0.0.1:6380>

これだけで終了です。このredis6380はredis6379のスレーブになりました。
非常に簡単です。はい。

でも毎回この作業をするのは面倒なので、設定ファイルに書いた方が良さそうです。

そのときに、前回チューニングで説明したredis.confの

slaveof host port
とか書かれている項目を見てください。これはredisを立ち上げるとき、対象のホストとポートを指定して、そのスレーブとして参加させるという意味になります。
複数のホストならこちらの方がいいでしょう。

2 レプリケーションの仕組みと機構

スレーブがレプリケーションに参加したときにまず何が起きるかを見ていきましょう。

① スレーブがレプリケーションに参加すると SYNCコマンドを実行してまずマスターと同期する

② マスターにBGSAVEが走ってスナップショットを作成し、スレーブは手元の古いスナップショットがあればそれを消去する。

③ マスターはさっき作ったスナップショットをスレーブに送りつける。さらに、マスターはこの間に書き込みがあった場合、それを覚えている。 スレーブは送られてきたスナップショットをパースしてスナップショットを同期する。

④ マスターは書き込みがあったこと分をスレーブに送りつける。スレーブはスナップショット以降の書き込みをマスターから受け取り、単純にそのコマンドを実行する。

これで同期完了。

さらに、レプリケーションはさらに連鎖できる。つまり、マスター スレーブ スレーブのスレーブ
というふうに、マスターが一つであれば、スレーブはいかなる形でもレプリケーションに参加できる。

さて、お待ちかねのQ & A

Q. え?マスター一つしかだめなの?

A. はい。スプリットブレインしたらまずいのでマスターは一般的なMySQLのマスタースレーブでよくある感じに一つだけです。さらに、書き込みもスレーブにしてはいけません。書き込みはマスターへ。読み込みはスレーブからが常套手段です。しかし、そもそも、スレーブに書き込みしようとするとエラーが帰ってくるので致命的な不整合にはなりませんが。。。

Q. スレーブのスレーブにする意味あるの?全部マスターのスレーブにおけばいいじゃん。

A. それはそうなんですが、実はスレーブの数がたくさんあると不都合が生じます。
それはI/Oです。例えば、マスター一つに対してスレーブが100個あったとすると、その100個に対してスナップショットを同期します。しかも同時に。すると、ネットワークの大域があっという間にパンクしてしまいます。パンクするとせっかく同期したのにマスターからスレーブが切断され、また同期とらなきゃいけません。

このため、例えば100個のスレーブに同期させたい場合は 10 × 10とまず分解します。マスター直下にスレーブが10個。スレーブのスレーブがそれぞれ10個。こうする事で、一気にかかる同期がさっきの1/10になって、マスターとその直下のスレーブのI/Oは軽減されます。

Q. フェイルオーバー機能とか無いの?

A. ありますが、デフォルトではないです。 Redis-Sentinelというのがあって、このツールを使うことでフェイルオーバーが可能です。
http://redis.io/topics/sentinel
機構としては、マスターとスレーブの振る舞いを監視しており、マスターとスレーブのPINGとマスターに対するPUB/SUBを組み合わせ、このsentinelプロセスがすべき情報を集める。
マスターが死ぬと、このsentinelがスレーブから一つだけマスターを選び、フェイルオーバーする。
そう。これはMongoDBに組み込まれているアービターのやってる事を引き受けるツールなのです。

次回、ロックとトランザクションについて見ていきましょう。