冗長構成

2013年07月17日

Redis Sentinel で冗長構成を組む際の注意点

はてなブックマークに登録

KVS界隈ではすっかりおなじみ(?)のRedisですが、当社でも徐々にそのニーズが高まってきました。
標準機能として、レプリケーション、Pub/Sub、ソート等の便利機能が満載のRedisですが、サービスに投入する際に冗長構成をどう組むかといった点が気になっている方もいるのではないでしょうか。
まだまだ検証中ではあるのですが、Redisに実装されているRedisSentinelを用いて冗長構成を組んだ際にハマった所をご紹介したいと思います。

RedisSentinelとは


Redisに標準実装されている機能の一つで、Redisのステータス監視、通知、自動フェイルオーバーが行なえます。
詳細な仕様、設定に関しては以下のドキュメントをご確認下さい。
http://redis.io/topics/sentinel

RedisSentinel導入前の構成

導入前
特に何の変哲も無い構成です。
Redisサーバ間ではRealIPを用いてレプリケーションを行ない、WEBサーバ上のアプリケーションからRedisを利用する際はMASTERに設定されているVIP宛にリクエストを出します。

RedisSentinel導入後の構成

導入後
RedisSentinelサーバを3台用意し、監視先の設定をVIPにしてみました。

各RedisSentinelの設定は共通で以下の様になっています。

1. sentinel monitor prod 192.168.8.1 6379 2
2. sentinel down-after-milliseconds prod 3000
3. sentinel failover-timeout prod 6000
4. sentinel can-failover prod yes
5. sentinel parallel-syncs prod 1
6. sentinel client-reconfig-script prod /opt/klab/sbin/redis_chroute.sh

監視先をVIPにすることで、障害発生時にRedisSentinelが再起動しても監視を続行出来るようにしてみました。
この検証時点ではRedis2.6.12を使用しており、一見想定通りに動作していた....ように見えたのですが、この設定のままでRedis2.6.13以降のバージョンへ置き換えた際に、問題が発生しました。
また、ドキュメントをよく読んだ方は既にお気づきかもしれませんが、バージョン関係なく障害発生時にSDOWNを検出できなくなる場合があります。

DEMOTE flag


まず、Redisのバージョンを2.6.13以降にした場合の問題から説明します。
Redis2.6.13以降、「DEMOTE flag」が追加されました。 疎通が取れずにODOWNとして扱われたMASTERに対して紐づくフラグです。 このフラグが立ったインスタンスに対し再び疎通が取れる様になった際、今現在のMASTER(旧SLAVE)となったRedisのSLAVEとして動作するように再設定が行なわれます。
さくっと冗長構成を組み直す事ができるので少し運用が楽になりそうな機能です。

しかし、VIPをRedisSentinelの監視先にした場合、上記機能の影響で問題が発生してしまいます。
各RedisSentinelはMASTERとSLAVEに関する情報を持っているのですが、障害発生前と障害発生後の状態を図にしてみました。

・障害発生前
障害前
ipportstatus
192.168.8.16379MASTER
10.13.0.26379SLAVE

・障害発生後
障害後
ipportstatus
192.168.8.16379DOWN
10.13.0.26379MASTER

フェイルオーバーが実施されると、SLAVEがMASTERへと昇格すると共にVIPも引き継がれます。
その際、RedisSentinelからはあたかも旧MASTERが復帰したように見えるため、今現在のMASTER(自分自身)へレプリケーションを行なうよう再設定を行なう結果となりました。
その結果、MASTER不在となりサービスに支障が出てしまいます。

SDOWNを検出できなくなる


これはドキュメントをよく読んで頂くとわかるのですが、RedisSentinelは障害(SDOWN)を検知すると、自分以外のRedisSentinelに対して「 is-master-down-by-addr 」コマンドを用いてMASTERの状況を問い合わせます。
この時、引数として障害が発生したと思われるMASTERのIPとポート番号が is-master-down-by-addr コマンドに与えられるのですが、この情報が各Sentinelの持つノード情報と一致する必要があります。
以下の図にあるように、フェイルオーバー後に特定のRedisSentinelを立ち上げ直した場合、同じMASTERに接続していても、IPとポート番号に差異が出てしまうためMASTERのステータスを正しく返すことができません。
ステータス


このような問題が起きた事から今現在はRedisSentinelの監視先をRealIPへと変更して検証を続けています。

【今回のまとめ】

* Redis Sentinelを利用して冗長構成を組む事が出来る。
* Redis2.6.13以降のバージョンを利用すると、運用が少し楽になるはず。
* RedisSentinelの監視対象は、VIPではなくReal IPを利用。

検証初期ではありますが、RedisSentinel非常に使いやすく便利だなという印象です。
また嵌った点が出た際にはこちらでご紹介させて頂きます。

klab_gijutsu2 at 16:02|この記事のURLComments(0)TrackBack(0)
2008年04月11日

repcached-2.0リリースのお知らせと、超簡単なサンプルコード

はてなブックマークに登録

repcached-2.0(memcached-1.2.5ベース) をリリースしましたのでお知らせします。

今回の目玉はマルチマスタ構成のサポートです。
以前のバージョンはマスタ/スレーブ構成だったので、必ずマスタへ書き込まなければいけませんでした。そのため、接続先のサーバがマスタなのかどうかをクライアントが判別しなければいけなかったり、keepalivedなどと併用するなどの工夫が必要でしたが、今回のバージョンではその必要がなくなります。両方のサーバに対してデータを書き込むことができるようになったので、かなり使いやすくなったと感じています。

repcachedはパフォーマンスを最重視しているため、レプリケーションは非同期で処理しています。したがって、setと同時にレプリケーションが完了する保証はありません。つまり、サーバAにsetした直後にサーバBからgetした場合、正しい値が返ってこない可能性があります。

しかし、memcachedのクライアントライブラリは負荷分散機能を持っていて、複数のサーバがある場合、キーのハッシュ値を元にして接続先のサーバが選択されます。そのため、同一のキーに対する操作は必ず同じサーバで処理されます。これを図にすると以下のような感じになります。

rep.png

つまり、クライアントライブラリの負荷分散機能を利用すると、データを格納したサーバと同じサーバが参照されるので、非同期処理に起因するデータの不整合は発生しません。そして、すべてのデータは両方のサーバへ格納されているので、片方のサーバがダウンしてもすべてのデータが保持されます。

down.png

ただし、参照しようとしたサーバがダウンしていた時に、自動的にもう片方のサーバへ参照しにいくかどうかは、クライアントライブラリの実装に依存します。例えば、PHP の memcached extension で提供される Memcache::set 関数の場合は、Version3.0.0以上ならば自動的に再接続してくれますが、Version2.2.3ではエラーになってしまいます。そのような場合は、自分で再試行するなどの処理を実装する必要があるかもしれません。セッションハンドラ(session.save_handler="memcache")を利用する場合は、バージョン2.2.3でも再接続してくれます。
※この例は後ほどご紹介します。

ダウンしていたサーバが復旧して最初にやることは、既存のサーバの全てのデータを複製(以下、まるごとこぴー)することです。その間、復旧中のサーバはクライアントからの接続を受け付けないので、誤って中途半端な状態のデータを取得してしまうことはありません。また、まることこぴーの最中でも、コピー元のサーバに対しては正常にアクセスできるので、サービスが停止してしまう心配もありません。

marugoto.png

まるごとこぴーが完了次第、レプリケーションを再開し、両方のサーバへアクセスできるようになります。まるごとこぴーの所要時間は、ギガビットイーサの環境で10万件で3秒程度、100万件で30秒程度でした。

簡単な使用例


 簡単な使用例として以下のコードを紹介します。セッション変数を利用して、リロードするたびにカウンタが増えていくPHPです。 セッションハンドラとしてmemcacheを使い、データの保存先にrcd1とrcd2というサーバを指定しています。rcd1とrcd2ではrepcachedを起動しておきます。

[count.php]
<?PHP
$rcd1="tcp://rcd1?persistent=1&weight=1&timeout=1&retry_interval=15";
$rcd2="tcp://rcd2?persistent=1&weight=1&timeout=1&retry_interval=15";
$session_save_path  = "$rcd1,$rcd2";
ini_set('session.save_handler', 'memcache');
ini_set('session.save_path', $session_save_path);
session_start();
if(empty($_SESSION['count'])){
   $_SESSION['count']=1;
} else {
   $_SESSION['count']++;
}
echo "count=".$_SESSION['count']."\n";
?>
※PHP-5.2.5 + memcache-2.2.3で動作確認

ブラウザでこのページへアクセスすると、リロードする度にカウンタが増えていきます。 rcd1,rcd2のどちらかが動いている限りカウンタは増え続け、両方停止するとリセットします。

このように、repcached-2.0はmemcachedを2台で負荷分散するのと同じ感覚で利用できます。 すでにmemcachedを2台構成で運用しているシステムであれば、repcached-2.0に置き換えるだけで冗長構成になるかもしれません。 さすがにオリジナルのmemcachedと比べると若干パフォーマンスは落ちますが、それでも実用には支障のないレベルに仕上がっていると思いますので、もしよろしければご利用下さいませ。


klab_gijutsu2 at 07:00|この記事のURLComments(0)TrackBack(1)
2006年09月20日

keepalivedの運用ノウハウお見せします 〜 設定ファイルを同期する

はてなブックマークに登録

keepalivedはLinuxで冗長構成を組む道具としてとても便利ですが、運用面に関する配慮に物足りなさを感じることがあります。例えばIncludeがないとかIncludeがないとかIncludeがないとか(笑)
naoyaの日記でnaoyaさんも悩んでいるようですが、設定ファイルをうまく保守する仕組みをどう作るかが導入する際の大きな鍵になると思います。今回は、DSASではどのようにして2台のkeepalivedを運用しているかを少しだけご紹介させて頂きたいと思います。

続きを読む
klab_gijutsu2 at 19:33|この記事のURLComments(0)TrackBack(3)
2006年08月30日

こんなに簡単! Linuxでロードバランサ (3)

はてなブックマークに登録

前回はkeepalivedを使ってWebサーバを冗長化してみました。
今回はkeepalivedのもう一つの機能であるVRRPを使って、ロードバランサ自身を冗長構成にしてみたいと思います。

続きを読む
klab_gijutsu2 at 13:07|この記事のURLComments(7)TrackBack(1)
2006年08月17日

いかにして冗長構成を作るか 〜DSASの場合〜

はてなブックマークに登録

DSASはいかにして可用性を高めているか、ちょっと紹介したいと思います。

今回は概略ということでざざざっと説明します。個別の構成についてはまた回を改めて紹介したいと思います。
続きを読む
klab_gijutsu2 at 15:51|この記事のURLComments(3)TrackBack(1)
Blog内検索
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント
最新トラックバック
Archives