mongodbを使ってみる (11) - replica set -

2013-01-24T00:00:00+00:00 MongoDB

マスターがあってスレーブがいくつかある、でマスターが落ちてもどっかのスレーブがマスターに昇格して運用を継続できるようにする的な事をやりたいのであれば、レプリカセットな機能を使えば良い模様

サーバーを起動

とりあえずマスター・スレーブとなる3つのMongoDBを起動

mongod --dbpath /tmp/mongo1 --logpath /tmp/mongo1/mongodb.log --port 10001 --replSet repltest --rest

mongod --dbpath /tmp/mongo2 --logpath /tmp/mongo2/mongodb.log --port 10002 --replSet repltest --rest

mongod --dbpath /tmp/mongo3 --logpath /tmp/mongo3/mongodb.log --port 10003 --replSet repltest --rest

でrepltestっていう名前でレプリカセット名を指定している感じなのかな、んまぁそういう感じで

でレプリカセットな設定を行う

rs.initiate({
  _id: "repltest",
  members: [
    { _id: 1, host: "localhost:10001" },
    { _id: 2, host: "localhost:10002" },
    { _id: 3, host: "localhost:10003" }
  ]
})

な感じで設定を行う。で http://localhost:11001/_replSet でレプリカセットの状態が見れるのでアクセスすると

っていう感じっすね。PRIMARYとSECONDARYの2つに分かれてる。でマスターを落とすと

てな感じで10001がDOWNになって10003がSECONDARYからPRIMARYになってる(10001は落ちてるので上のWebコンソールは別のサーバーのやつでアクセスする)。でこの状態で現在は10003がPRIMARYなのでこれも落としてみると

でそこら辺を柔軟に管理してPRIMARY/SECONDARYを監査してくれる?のがArbiterな模様なので、もう1個MongoDBを起動する

mongod --replSet repltest --dbpath /tmp/mongo4 --logpath /tmp/mongo4/mongdb.log --port 10004 --rest

この状態でもう一度上記の3つのサーバー起動しておく。でWebコンソールからPRIMARYに入って

db.addArb("localhost:10004")

でArbiterサーバーを設定しておく。で再度Webコンソールを見ると

な感じARBITERな項目が増える。でちょっと停止させておいて、既に3つのサーバーをレプリカセットとして認識させているけど、10003だけ起動せずに停止したままにしてみると

という風に10003が起動してないのでPRIMARYが決まってない。こういう状況になった場合にArbiterがPRIMARYを監査してくれる模様という事で停止しておいたArbiterを起動すると

っていう感じ。まぁPRIMARYかSECONDARYか判断されてないようなケースだとArbiterにそれを委譲するっていう感じなんすかね。はっきりとした理論は無いんですけど

んまぁレプリカセットな概要的なのはこんな感じかと

で問題はデータとかどうなんの的な話になると思うんですが、PRIMARYが停止してSECONDARYがPRIMARYに昇格する際にPRIMARYが持ってたデータをsyncする模様。元々SECONDARYの状態で既に持ってるけどSECONDARYだからfind出来ないsave出来ない状態なので確認できないんですが、んまぁロックされててPRIMARYに昇格したらロック解除されて参照できるようになるっていう感じかなーっと

でクライアントとかだとレプリカセットに指定されているサーバーを指定すれば良い模様。PRIMARYになってる所にデータが行くっていう感じかと。Perlだと

use MongoDB;

my $c = MongoDB::MongoClient->new(
    host => "mongodb://localhost:10001,localhost:10002,localhost:10003"
);
my $db = $c->get_database("sample");
my $coll = $db->get_collection("samples");

$coll->save(+{ time => time() });

っていう感じでhostでレプリカセットで指定されているサーバーを指定する

まぁドキュメント見た方が理論的でいいかと

ちなみにArbiter運用でレプリカセットを運用する場合に最低でも必要なサーバー数は「N > 2」な感じじゃないかと。最低でも2桁なサーバー数無いと辛そうな気がします

fluent-plugin-mongoに突っ込んでみる NPAPIをざっくりやってみる (1)