Tumblr最近必要に迫られて、ようやくRedisをインストールして触ってみました。(Redis童貞からの脱却)色々と、基本部分ではあるけど、せっかく実際に触りながら勉強したので、このエントリにメモしておこうと思います。使ってみたRedisのバージョンは、stableの最新版である2.8.7です。Vol.73のRedis特集(2.6向けではありますが)にほとんど書いてあるので読むべし。見るさて、話は戻って、ここからが本題。前提として試してみた環境は、サーバを3台用意して、その各サーバで"redis"プロセスと"redis-sentinel"プロセスを起動させるような構成です。このエントリでは、設定の詳細というよりはコマンドレベルでのオペレーションとか気になった挙動について書こうと思う。2.8.7のRPMファイルを自作していますが、ベースのSPECファイルはRemiリポジトリのものを参考にさせてもらいました。以下リンク先より、ダウンロードできるRPMで同様のことができるはず。1sysctl.confでこの辺の設定を有効にしておくとか。あとは、maxclientsの数にあわせてlimits.confでFDの上限を増やしておくとか。startredis-serverコマンドでもよい。shutdownちゃんとRedis内のコマンドで終了させるが吉のようだ。bye...正常に終了されると、上記のような感じのログになる。stop"で終了させた場合。disk"が出力されず[FAILED]と表示されてコワい。(まー、この辺はスクリプト書き直せよ、って話ではある。)インメモリデータの永続化についてRedisには、インメモリのデータを定期的にスナップショットする(ディスクに書き落とす)仕組みがある。設定ファイルの"save"項のパラメータに従って自動でやってはくれるが、手動でディスクに書き込むためには以下のRedisのコマンドをたたく。save全てのデータセットをディスクに保存する。保存が完了するまではデータベースにアクセスできなくなる。bgsaveディスクへの保存処理をバックグラウンドで行ってくれる。(フォークして子プロセスが処理してくれてる。)保存中もデータへのアクセスは読み書きともに可能。1394162355最後にスナップショットが取られた時刻は↑のような感じで確認できるが、UNIXTIMEである。12:19:15なので、古典的ではあるが、dateコマンドをかませば、もう少しビジブルな感じで確認できたりもする。File(AOF)モードRedisのデフォルトのデータ永続化は、上記のスナップショットで、↑にも書いたが定期的にスナップショットを行っている。10000これは、最後にSAVE(保存)されてから、900秒以内に1個以上のkeyが更新された場合300秒以内に10個以上のkeyが更新された場合60秒以内に10000個以上のkeyが更新された場合のいずれかの条件を満たした場合に、BGSAVEを実行するという動作を意味します。これだとマスタに予期せぬダウンが生じた場合に、永続化しているとはいえ、タイミングによっては直近のデータをロストする(失う)ことになります。File(AOF)モードが用意されていて、これは変更操作を全てログに保存するモードになります。MySQLでいうバイナリログみたいなもの。(って書くと突っ込まれるか...)ログファイルへの出力タイミングは「常に(always)」「1秒ごと(everysec)」「fsyncせずOSに書き出しを任せる(no)」の3種類です。設定は"appendonly"をyesにして起動すればOK。yesを実行して、オンラインでAOFを有効にしてから、設定ファイルを変更するなりします。ちなみに、スナップショットに比べて、AOFのログファイルサイズは結構大きくなります。そのため、定期的に再構成が実行されます(バックグラウンドで実行される)。再構成が実行されると、ログファイルがコンパクトになり、以下のようなRedisのログが出力されます。successfully手動で、AOFの再構成を行う以下のコマンドを実行すべし。バックグラウンドで実行される。bgrewriteaofAOFファイルのチェックredis-check-aofコマンドで行う。validこんな感じ。壊れていた場合は、"--fix"オプションで修復できるとのこと。レプリケーションの設定Redisはマスタに対して複数のスレーブをもてるし、スレーブのスレーブ(孫スレーブ)も作れる。非同期I/Oによるレプリケーション。なっている)設定は、スレーブ側のredis.confに以下の記載をする。6379IPアドレスのところは、名前解決できるホスト名/FQDNとかでもよい。マスタのRedisを6379ポートで待ち受けていない場合は、6379のところを設定しているポート番号に変える。6379ちなみに、こんな感じでRedisのコマンドでも可能。レプリケーションがはられると、以下のような感じでINFOコマンドで確認できる。マスタ側から見ると、どのホストがスレーブなのかと、その状態が分かる。スレーブ側から見ると、マスタへのレプリケーションのステータスとかがわかります。個人的には、冗長構成を意識したときに、設定ファイルにマスタのありか(IPアドレスとか)を書いておくと、マスタが変更されたときに怖いことが起こる可能性があるので、設定ファイルには書かずにredis-cliとかで設定しておくのが良いのかなと思っていました。Sentinelを使っていると、sentinel君が勝手にredis.confに、slaveofを書いてくれたりします・・・wいずれにせよ、マスタ/スレーブの状態管理は、基本的にSentinelに任せてしまう形がいいと思っている。oneスレーブ側から上記のRedisコマンドをたたくと、マスタから切り離される。追記Sentinel構成でのスレーブノード切り離しは以下リンク先を参考にしてください。Sentinelを使うと、各サーバのRedisプロセス(マスタ/スレーブ)の状態を監視してくれ、マスタに問題が発生したら、別のスレーブへ自動でフェイルオーバーしてくれるようになります。1Sentinelの設定ファイル(/etc/redis-sentinel.conf)は、↑のような感じにした。今回、Sentinelは3台構成なので、quorumの数は"2"にしている。[start|stop]ちなみに、Sentinelの起動/停止は、以下のような感じ。Sentinelは起動すると、設定してあるRedisのマスタノードにアクセスを行い、レプリケーションまわりの情報などを取得し、スレーブノードを把握します。設定ファイルを確認すると、それらの情報が自動的に書き込まれていることがわかります。下記リンク先で、けんじおじさんも書いているけど、Split-brain-syndromeを防ぐ意味でも、複数台のSentinelを出来る限りネットワーク構成を意識して、動かしておくべきだと思う。http://blog.kenjiskywalker.org/blog/2013/01/24/redis-sentiel-howto/マスタ/スレーブのノード情報をSentinelに尋ねるマスタネームの部分(mymaster)は、適宜置き換えてください。(26379番ポートはSentinelプロセスがLISTENしているポート番号。実際にマスタを落とすとどういうことが起こるかログで追ってみる。登場人物は以下の3つ。旧マスタ(今からダウンする。)新マスタ(元々はスレーブ。旧マスタのダウン後に、新マスタとして昇格)スレーブ(基本的にスレーブのままだったノード)まず、テストのため旧マスタをダウンさせる。6379この時、スレーブのノードのsentinelのログを見ると、しばらく(およそ"down-after-milliseconds"の設定値)して旧マスタのsdownを検知。(自身のSentinelプロセスが旧マスタのダウンを検知。6379そこから、リーダーの選出および、旧マスタのodownを検知。2/2"の記載がありますね。そこから新マスタが選ばれて、switch-masterが走ります。6379そして、Sentinelの持つ情報としてスレーブ情報の更新をします。旧マスタがスレーブへと降格して、ダウンした状態であることが検出されます。Sentinelを使っていると手動でフェイルオーバーさせることもできます。意図的に実施するので、フェイルオーバーというよりはテイクオーバーと言うべきか。mymasterこんな感じで実行すると、別のスレーブがマスタへと昇格し、旧マスタはスレーブになります。マスタネームの部分(mymaster)は、適宜置き換えてください。スレーブの再投入さて、ここまで↑の流れで旧マスタはダウンしたままですが、復帰させてみます。この時点で、旧マスタはRedisプロセスもSentinelプロセスも停止したままです。旧マスタのRedisプロセスを起動します。6379すると、他のSentinelから復旧したことが検知(sdownステータスが消滅)され、この時点でスレーブとしてレプリケーションが始まります。優秀な子なの・・・!次に、Sentinelの設定ファイルは、マスタの指定として、旧マスタが指定されたままの状態ですが、あえてこのままSentinelプロセスを起動してみましょう。6379すると、こんな感じで、Duplicateが検知され、正しい情報に直されて問題なく起動しました・・・。Sentinelの設定ファイルも正しいマスタ/スレーブの情報が記載されています。試しにまっさらなスレーブ(ゼロデータ)を作って、適当なテストデータを持つ、約2500万Key、約7.0GBメモリデータ量、RDBファイル(後述)約1.9GBで構成されたマスタに対して、レプリケーションをはってみます。ログを見るとわかりやすいですが、以下のような挙動です。CentOS6系KVMによる仮想マシン」だと、上記のような感じでした。転送に49秒、メモリへのロードに55秒ですね。このあたりはマシンのスペックやネットワーク環境に依存しますので、参考までに。master"というログが出力されて検知されます。その後、設定が正しいステータスに修正されて動き続けるため、心配ご無用でした。Resynchronization)と呼ばれる部分的な再同期の仕組みをRedisはサポートしています。Redisバージョン2.8以前では、マスタとスレーブのレプリケーションリンクがダウンした際に、完全な再同期が必要だったみたいですが、2.8以降では部分的な再同期をサポートしています。2.8では、レプリケーションストリームをメモリ内のバックログで保持していて、レプリケーションリンクがダウンした後、スレーブがマスタに再接続にいった際に、これまでレプリケーションを行っていたマスタ実行IDをリクエストし、一致していてかつ指定されたオフセットがレプリケーションのバックログから利用可能であれば、レプリケーションが中断されたところから、再開(部分的に同期)します。resynchronizationを試みています。one)ときは、いったんマスタの情報(ID)を失うことになるので、その後もう一度レプリケーションリンクを作成しても、完全な再同期となります。あと、レプリケーションのバックログのサイズやTTLに関しては、repl-backlog-sizerepl-backlog-ttlあたりで指定可能です。<antirez>スレーブとして投入する際、持っているデータがマスタと違った場合マスタが保持しているデータが正しい状態と認識し、スレーブは完全にマスタのデータと同期される状態になる。(非同期なレプリケケーションをしている以上、タイミングによってはマスタとスレーブのデータがずれてしまうこともあるため、フェイルオーバー時などのデータの取り扱いは注意しておくべし。slaveという構成だったとしよう。この3台のうち、redis01だけネットワーク分断が発生して独立してしまったとする。redis01だけ疎通が取れない状態なので、redis02とredis03は協調して、マスタのフェイルオーバーを行い、redis01はslave扱いにする。redis01は、redis02とredis03のスレーブノードがダウンしたという判定をしてマスタであり続ける。その結果、以下のような状態となる。slave次に、ネットワーク分断していたredis01を再びネットワーク疎通が取れた場合、他sentinelの状態を確認し、switch-masterを行い、自身をスレーブにする。その結果、以下の構成となる。slaveなかなか優秀な挙動だ。実行するとデータがディスクへと保存される。(セーブが完了したかは、LASTSAVEコマンドで確認しましょう)バックアップはそのファイルを別の場所にとっておけばいい。ファイルは、redis.confで設定されている"dir"のディレクトリに、"dbfilename"で設定しているファイル名で取得されているはず。Redis尚、RDBファイルは普通にコピーして保存すればよいとの事。RDBファイルのチェックRedisには「redis-check-dump」という、RDBファイルに問題が無いかを確認するコマンドがある。OKこんな感じで実行してチェックすることができる。リストアバックアップの逆のことをすれば良いだけ。"dbfilename"に従って配置し、Redisを起動すればOKです。IPv6での対応IPv6環境でも稼動させてみたが、Redisプロセス自体は軽く確認していた限り問題なく動いている。Sentinel側で、各ノードのIPv6アドレスが正常な形式で取得できず、きちんと動作しない。マスタのダウンを検知して、フェイルオーバー処理は行うものの、途中で全Sentinelプロセス自体がクラッシュして落ちる始末。TRACE実は、IPv6を検証したのはバージョン2.8.6ではあったのだが、、、上記のようなログが出力されて落ちた。設定を変更するオペレーション例えば、maxmemoryを増やすオペレーションをやってみる。単純だが以下の2通り。8589934592上記は、maxmemoryを8GBに変更した例。CentOS6系KVMによる仮想マシン。マスタのデータは、約2500万Key、約7.0GBメモリデータ量、RDBファイル(後述)約1.9GBな状態。AOFは無効マスタ1に対してスレーブ2な環境。マスタにてredis-benchmarkコマンドをローカルに対して実施。1Gbps)な環境で取得すると、Maxが65000reqests/secあたりでキャップされていた。Sentinelまわりの挙動について検証された結果が記載されている。Tumblr関連記事2014-04-10RedisをSentinel構成で運用しているときのSlaveノードの切り離しRedisでSentinelを使った構成で組んでいると、レプリケーション...2014-03-25IT系の文章をWebで翻訳するなら、やっぱりGoogle翻訳かなと思った。@namikawaメールアドレス執筆・講演依頼や、その他ご連絡は、以下のメールアドレスまでお願いします。お問い合わせスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。