mongoでレプリカセット作ってみる

# 準備
EC2で3台構成で試す。
mongoのバージョンは3.2.9
Primary(db1), Secondary(db2), Arbiter(db3)の構成

```
wget http://downloads.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.2.9.tgz
```

# confの設定とmongodの起動

内容は下記の通り

```
[root@db1 mongodb]# cat conf/rs01.conf 
port = 27011
dbpath = /root/mongodb/data/rs01
fork = true
replSet = rs01
logpath = /root/mongodb/logs/mongors01.log
logappend = yes
smallfiles = true
storageEngine = wiredTiger
```

mongodプロセスを各サーバで起動する

```
./bin/mongod -f conf/rs01.conf 
```

# レプリカセットの設定

```
[root@db1 mongodb]# ./bin/mongo --port 27011 --eval "rs.initiate()"
MongoDB shell version: 3.2.9
connecting to: 127.0.0.1:27011/test
{
        "info2" : "no configuration specified. Using a default configuration for the set",
        "me" : "db1:27011",
        "ok" : 1
}
[root@db1 mongodb]# ./bin/mongo --port 27011 --eval "rs.add('db2:27011')"
MongoDB shell version: 3.2.9
connecting to: 127.0.0.1:27011/test
{ "ok" : 1 }
[root@db1 mongodb]# ./bin/mongo --port 27011 --eval "rs.addArb('db3:27011')"
MongoDB shell version: 3.2.9
connecting to: 127.0.0.1:27011/test
{ "ok" : 1 }
[root@db1 mongodb]# ./bin/mongo --port 27011 --eval "var config = rs.config(); config.members[0].priority=2; rs.reconfig(config);"
MongoDB shell version: 3.2.9
connecting to: 127.0.0.1:27011/test
{ "ok" : 1 }

[root@db1 mongodb]# ./bin/mongo --port 27011 --eval "rs.status()"
MongoDB shell version: 3.2.9                                                                                             
connecting to: 127.0.0.1:27011/test
{
        "set" : "rs01",
        "date" : ISODate("2017-01-29T05:19:51.778Z"),
        "myState" : 1,
        "term" : NumberLong(1),
        "heartbeatIntervalMillis" : NumberLong(2000),
        "members" : [
                {
                        "_id" : 0,
                        "name" : "db1:27011",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 784,
                        "optime" : {
                                "ts" : Timestamp(1485667161, 1),
                                "t" : NumberLong(1)
                        },
                        "optimeDate" : ISODate("2017-01-29T05:19:21Z"),
                        "electionTime" : Timestamp(1485666794, 2),
                        "electionDate" : ISODate("2017-01-29T05:13:14Z"),
                        "configVersion" : 4,
                        "self" : true
                },
                {
                        "_id" : 1,
                        "name" : "db2:27011",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 328,
                        "optime" : {
                                "ts" : Timestamp(1485667161, 1),
                                "t" : NumberLong(1)
                        },
                        "optimeDate" : ISODate("2017-01-29T05:19:21Z"),
                        "lastHeartbeat" : ISODate("2017-01-29T05:19:49.930Z"),
                        "lastHeartbeatRecv" : ISODate("2017-01-29T05:19:49.929Z"),
                        "pingMs" : NumberLong(10),
                        "syncingTo" : "db1:27011",
                        "configVersion" : 4
                },
                {
                        "_id" : 2,
                        "name" : "db3:27011",
                        "health" : 1,
                        "state" : 7,
                        "stateStr" : "ARBITER",
                        "uptime" : 317,
                        "lastHeartbeat" : ISODate("2017-01-29T05:19:51.680Z"),
                        "lastHeartbeatRecv" : ISODate("2017-01-29T05:19:51.672Z"),
                        "pingMs" : NumberLong(0),
                        "configVersion" : 4
                }
        ],
        "ok" : 1
}
```

# サンプルデータの投入と確認

Primary(db1)にデータ投入

```
[root@db1 mongodb]# ./bin/mongo --port 27011                                                                             
MongoDB shell version: 3.2.9
connecting to: 127.0.0.1:27011/test
rs01:PRIMARY> use mydb                                                                                                   
switched to db mydb
rs01:PRIMARY> for(var i=0; i<10000; i++) db.logs.insert({"uid":i, "value":Math.floor(Math.random()*10000+1)})            
WriteResult({ "nInserted" : 1 })
rs01:PRIMARY> db.logs.count()                                                                                            
10000
```

Secondary(db2)で確認

```
[root@db2 mongodb]# ./bin/mongo localhost:27011/mydb                                                                     
MongoDB shell version: 3.2.9
connecting to: localhost:27011/mydb
rs01:SECONDARY> db.getMongo().setSlaveOk()                                                                               
rs01:SECONDARY> db.logs.count()                                                                                          
10000
```

# pymongoで確認
localhostからEC2へリクエストする

```
$ python -V
Python 3.5.1
$ pip list | grep pymongo
pymongo (3.4.0)
```

下記のようなコードを書いて実行する。
(/etc/hosts以下に名前解決できるように記述をしている。)

```py3
from pymongo import MongoClient                                                                                          
from time import sleep

c = MongoClient(host=['db1:27011', 'db2:27011', 'db3:27011'], replicaset='rs01')                                         
print(c.mydb.logs.count())                                                                                               
print(c.nodes)  
```

```
$ python req.py 
10000
frozenset({('db1', 27011), ('db3', 27011), ('db2', 27011)})
```

ためしにPrimary(db1)を落としてみる

```
[root@db1 mongodb]# pgrep -lf mongo                                                                                      
2654 ./bin/mongod -f conf/rs01.conf
[root@db1 mongodb]# pkill -f mongo
[root@db1 mongodb]# pgrep -lf mongo
[root@db1 mongodb]# 
```

db2がPrimaryに昇格している

```
[root@db2 mongodb]# ./bin/mongo localhost:27011/mydb --eval "rs.status()"
MongoDB shell version: 3.2.9
connecting to: localhost:27011/mydb
{
        "set" : "rs01",
        "date" : ISODate("2017-01-29T05:58:54.369Z"),
        "myState" : 1,
        "term" : NumberLong(2),
        "heartbeatIntervalMillis" : NumberLong(2000),
        "members" : [
                {
                        "_id" : 0,
                        "name" : "db1:27011",
                        "health" : 0,
                        "state" : 8,
                        "stateStr" : "(not reachable/healthy)",
                        "uptime" : 0,
                        "optime" : {
                                "ts" : Timestamp(0, 0),
                                "t" : NumberLong(-1)
                        },
                        "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
                        "lastHeartbeat" : ISODate("2017-01-29T05:58:53.729Z"),
                        "lastHeartbeatRecv" : ISODate("2017-01-29T05:58:19.930Z"),
                        "pingMs" : NumberLong(0),
                        "lastHeartbeatMessage" : "Connection refused",
                        "configVersion" : -1
                },
                {
                        "_id" : 1,
                        "name" : "db2:27011",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 3108,
                        "optime" : {
                                "ts" : Timestamp(1485669512, 1),
                                "t" : NumberLong(2)
                        },
                        "optimeDate" : ISODate("2017-01-29T05:58:32Z"),
                        "infoMessage" : "could not find member to sync from",
                        "electionTime" : Timestamp(1485669511, 1),
                        "electionDate" : ISODate("2017-01-29T05:58:31Z"),
                        "configVersion" : 4,
                        "self" : true
                },
                {
                        "_id" : 2,
                        "name" : "db3:27011",
                        "health" : 1,
                        "state" : 7,
                        "stateStr" : "ARBITER",
                        "uptime" : 2659,
                        "lastHeartbeat" : ISODate("2017-01-29T05:58:53.712Z"),
                        "lastHeartbeatRecv" : ISODate("2017-01-29T05:58:52.564Z"),
                        "pingMs" : NumberLong(0),
                        "configVersion" : 4
                }
        ],
        "ok" : 1
}
```

リクエストは問題なく処理されている

```py3
from pymongo import MongoClient                                                                                          
from time import sleep
                                                            
c = MongoClient(host=['db1:27011', 'db2:27011', 'db3:27011'], replicaset='rs01')                                         
print(c.mydb.logs.count())                                                                                               
print(c.nodes) 
```

```
$ python req.py 
10000
frozenset({('db3', 27011), ('db2', 27011)})
```