MongoDBでReplica Setsを試した時のメモ

MongoDBでReplica Setsを試した時のメモ

複数のDBプロセスをクラスタリングすることで、いざという時のマシンダウンに対応できる冗長性を確保する。フェイルオーバーとかってことです。

で、これが簡単でござった。mongoばんざい。nodeばんざい。JavaScriptばんざい。

マシンは、こないだのこれ http://qiita.com/items/4ea61f8ba0470ec3d5be を利用してみます。今回はルーターや仮想IP部分などは関係ないので図の下半分のオレンジ色のあたりだけ見てください。

![MongoDBでReplica Setsを試した時のメモ](https://cacoo.com/diagrams/ZQq47Rk9Ap4R86FN-AA6F6.png?t=1346291630101)

#レプリカマシンのリスト

当初3台の予定だったのだけれど、とりあえず先に下記2台のローカルLAN内PCで組みはじめることにする。あとで、1台追加します。

192.168.1.11
192.168.1.12
192.168.1.13(あとから追加)

#各マシンへnpmとかインストール

```
sudo apt-get install mongodb
npm install mongoose@2.7.3
```

念のためにバージョンはこれです。mongooseのv3では今のところmongoose.connectSetがundefinedになってしまったので、、、。
※注意　下記コメントの追記を参照
[追記　2016/10/03 mongoose@4.4.20を使う場合](http://qiita.com/toshirot/items/b5e99bf4923b84b2bb40#comment-034571d56b75357a6099)

```
npm ls mongodb
└─┬ mongoose@2.7.3
  └── mongodb@1.1.2 

mongod -version
db version v2.0.4, pdfile version 4.5
Mon Aug 27 14:08:38 git version: nogitversion
```

#とりあえずLAN内の2台で組む

とりあえず、最初は192.168.1.11をプライマリ、192.168.1.12をセカンダリとすることにして、、、

それぞれのPCに同じようにdbディレクトリとlogディレクトリを作りmongodを起動してみた。

--journalを使い、--rest可能にして、--port 27020を使ってみる。--forkはデーモン化するためのもの。--dbpath、--logpathは読んで字のごとく。

```192.168.1.11
mkdir -p ./mongodb/db1
mkdir -p ./mongodb/db1-log
mongod --rest --journal --replSet myset --port 27020 --dbpath ./mongodb/db1 --fork --logpath ./mongodb/db1-log/db.log --logappend
```
以下も内容は同じ

```192.168.1.12 
mkdir -p ./mongodb/db1
mkdir -p ./mongodb/db1-log
mongod --rest --journal --replSet myset --port 27020 --dbpath ./mongodb/db1 --fork --logpath ./mongodb/db1-log/db.log --logappend
```

#設定

次に、一呼吸おいて、192.168.1.11へ設定する


```192.168.1.11
mongo 192.168.1.11:27020

>config = {_id: 'myset', members: [
   {_id: 0, host: '192.168.1.11:27020'},
   {_id: 1, host: '192.168.1.12:27020'}
  ]
}
>rs.initiate(config);

```

#もう出来上がりっ！

具体的にはこんな感じの会話になります。

```
hoge@192.168.1.11:~$ mongo 192.168.1.11:27020
MongoDB shell version: 2.0.4
connecting to: localhost:27020/test
> config = {_id: 'myset', members: [
...    {_id: 0, host: '192.168.1.11:27020'},
...    {_id: 1, host: '192.168.1.12:27020'}
...   ]
... }
{
        "_id" : "myset",
        "members" : [
                {
                        "_id" : 0,
                        "host" : "192.168.1.11:27020"
                },
                {
                        "_id" : 1,
                        "host" : "192.168.1.12:27020"
                }
        ]
}
> rs.initiate(config);
{
        "info" : "Config now saved locally.  Should come online in about a minute.",
        "ok" : 1
}

```

#動いてる？


```
hoge@192.168.1.11:~$ ps ax | grep mongo
  854 ?        Ssl   10:27 /usr/bin/mongod --config /etc/mongodb.conf
11481 pts/0    Sl+    0:00 mongod --rest --journal --replSet myset --port 27020 --dbpath ./mongodb/db1
16254 pts/1    S+     0:00 grep --color=auto mongo

hoge@192.168.1.12:~/usiku$ ps ax | grep mongo
26490 pts/4    Sl+    0:00 mongod --rest --journal --replSet myset --port 27020 --dbpath ./mongodb/db1
26796 pts/2    S+     0:00 grep --color=auto mongo
```

こんな感じ。ちなみに、ここで、それぞれのマシンにアクセスするとプライマリとセカンダリをプロンプトに表示します。


```
hoge@192.168.1.11:~$  mongo 192.168.1.11:27020
MongoDB shell version: 2.0.4
connecting to: 192.168.1.11:27020/test
PRIMARY> 

hoge@192.168.1.12:~$ mongo 192.168.1.12:27020
MongoDB shell version: 2.0.4
connecting to: 192.168.1.12:27020/test
SECONDARY> 


exitで終了 helpでヘルプ
```

#問題発生

3台のマシンで試した時には、PRIMARYをkillすると、自動的にSECONDARYのいずれかがPRIMARYに代わって何事もなかったかのように動作し続けられたのですが、、、

この2台の構成でPRIMARYをkillしてもSECONDARYはPRIMARYに昇格してくれないのです。

これは、フェイルオーバー時に誰をPRIMARYに昇格するかという投票システムがこの構成では機能しないのかなぁ( 参考：http://www.mongodb.org/display/DOCS/Replica+Sets+-+Voting　)。

ということで、明日時間が取れたら、当初計画通り、もう一台rs.addしようと思います。

ちなみにkillしたマシンも再度下記おまじないをかけると、、、

```
mongod --rest --journal --replSet myset --port 27020 --dbpath ./mongodb/db1 --fork --logpath ./mongodb/db1-log/db.log --logappend
```

復帰しますが、今度はmongo localhost:27020 で確認するとSECONDARYに降格されていて、その間一人で頑張っていたマシンの方が今度はPRIMARYに昇格していることがわかります。

頑張れば評価されるのです。

#arbiterなマシンを3台目として追加してみる
192.168.1.11や12のようなレプリカを引き受けるマシンはrs.addメソッドで追加します。

それで、今後必要な時に何台も追加していくことができるわけです。

でも、今回は単に障害時にどのマシンをPRIMARYにするかという判定のお手伝いだけするarbiterというタイプのマシンをrs.addArbメソッドで追加してみます。

まず、192.168.1.13のコマンドライン側のおまじないは同じです(pathやlog用のディレクトリ名だけ一応わかりやすいように変えてはありますが)。

```
mkdir -p ./mongodb/db1-arbiter
mongod --rest --journal --replSet myset --port 27020 --dbpath ./mongodb/db1-arbiter --fork --logpath ./mongodb/db1-arbiter/db.log --logappend
```

で、こういうメソッドの発行はPRIMARY側のマシンからやります。arbiterとして追加するので rs.addArb('192.168.1.13:27020')と打ってます。

```
hoge@192.168.1.11:~$  mongo 192.168.1.11:27020
MongoDB shell version: 2.0.4
connecting to: 192.168.1.11:27020/test
PRIMARY> rs.addArb('192.168.1.13:27020')
```

このあと、rs.status()とでも打って、数秒～数十秒？程度様子をみてると、変更された内容を確認できます。

#HTMLで情報が見れます

http://192.168.1.11:28020 ポート27020に1000足した28020へアクセスするとHTMLで情報が見れます


#マングースで使う

普通は、下記のように接続しますが、、、

```
var piyodb = mongoose.createConnection('mongodb://localhost/piyo');
```

こんな感じで使います。

```
//レプリカリスト
var ReplicaSets = ''
  + 'mongodb://192.168.1.11:27020/piyo,'
  + 'mongodb://192.168.1.12:27020/piyo,'
  + 'mongodb://192.168.1.13:27020/piyo,' //追加

// DB接続
var piyodb = mongoose.connectSet(ReplicaSets);
```

#関連
mongo のレプリカセットと複数WebSocket サーバーのフェールオーバーメモ
http://qiita.com/toshirot/items/a555179e95990ca89bf7
#参考

Replica Set Commands
http://www.mongodb.org/display/DOCS/Replica+Set+Commands

MongoDBのReplica Setsについての概要
http://d.hatena.ne.jp/ryopeko/20101005/1286262922
MongoDBのレプリケーションとバックアップ機能の紹介
http://doryokujin.hatenablog.jp/entry/20101102/1288651712
mongodbのreplica set
http://d.hatena.ne.jp/rougeref/20110727

MongoDBの新機能：ジャーナリングについて詳しく
http://doryokujin.hatenablog.jp/entry/20110614/1308010072
http://www.mongodb.org/display/DOCS/Journaling

[MongoDB]MongoDBのRESTインタフェースを使う
http://d.hatena.ne.jp/shokai/20110723/1311370610
http://www.mongodb.org/display/DOCS/Http+Interface

MongoDBのReplica Setを設定する
http://inet-lab.naist.jp/mongodb-replica-set/