MongoDBのレプリカセット

MongoDBのレプリカセットを触ってみる。

ディレクトリ作成

今回は1台のサーバで複数のMongoDBを起動するので、各MongoDB用のディレクトリを作成する。

mkdir -p /data/mongo{1,2,3}/{db,logs}

MongoDB起動

port、logpath、pidfilepath、dbpathを変えて3つ起動させる。
レプリカセットを組むには起動オプションに--replSet レプリカセット名を付与する。

/usr/local/mongodb/bin/mongod --replSet sampleset --journal --port 27017 --logappend --logpath /data/mongo1/logs/mongod.log --pidfilepath=/data/mongo1/logs/mongod.pid --dbpath=/data/mongo1/db --fork
/usr/local/mongodb/bin/mongod --replSet sampleset --journal --port 27018 --logappend --logpath /data/mongo2/logs/mongod.log --pidfilepath=/data/mongo2/logs/mongod.pid --dbpath=/data/mongo2/db --fork
/usr/local/mongodb/bin/mongod --replSet sampleset --journal --port 27019 --logappend --logpath /data/mongo3/logs/mongod.log --pidfilepath=/data/mongo3/logs/mongod.pid --dbpath=/data/mongo3/db --fork

レプリカセット設定

以下ではPRIMARY以外のサーバはstateStrがRECOVERINGになっているが、しばらくするとSECONDARYになる。

root@johan:~# /usr/local/mongodb/bin/mongo
MongoDB shell version: 2.0.2
connecting to: test
> config = {_id:'sampleset',members:
... [
...     {_id:0, host:'localhost:27017', priority:1},
...     {_id:1, host:'localhost:27018', priority:1},
...     {_id:2, host:'localhost:27019', priority:1},
... ]}
{
	"_id" : "sampleset",
	"members" : [
		{
			"_id" : 0,
			"host" : "localhost:27017",
			"priority" : 1
		},
		{
			"_id" : 1,
			"host" : "localhost:27018",
			"priority" : 1
		},
		{
			"_id" : 2,
			"host" : "localhost:27019",
			"priority" : 1
		}
	]
}
> rs.initiate(config)
{
	"info" : "Config now saved locally.  Should come online in about a minute.",
	"ok" : 1
}
> rs.status()
{
	"set" : "sampleset",
	"date" : ISODate("2012-02-22T13:01:05Z"),
	"myState" : 1,
	"members" : [
		{
			"_id" : 0,
			"name" : "localhost:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"optime" : {
				"t" : 1329915647000,
				"i" : 1
			},
			"optimeDate" : ISODate("2012-02-22T13:00:47Z"),
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "localhost:27018",
			"health" : 1,
			"state" : 3,
			"stateStr" : "RECOVERING",
			"uptime" : 17,
			"optime" : {
				"t" : 0,
				"i" : 0
			},
			"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
			"lastHeartbeat" : ISODate("2012-02-22T13:01:04Z"),
			"pingMs" : 20454919,
			"errmsg" : "initial sync need a member to be primary or secondary to do our initial sync"
		},
		{
			"_id" : 2,
			"name" : "localhost:27019",
			"health" : 1,
			"state" : 3,
			"stateStr" : "RECOVERING",
			"uptime" : 17,
			"optime" : {
				"t" : 0,
				"i" : 0
			},
			"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
			"lastHeartbeat" : ISODate("2012-02-22T13:01:04Z"),
			"pingMs" : 0,
			"errmsg" : "initial sync need a member to be primary or secondary to do our initial sync"
		}
	],
	"ok" : 1
}
PRIMARY> exit
bye

プライマリにデータを登録

root@johan:~# /usr/local/mongodb/bin/mongo
MongoDB shell version: 2.0.2
connecting to: test
PRIMARY> use mydb
switched to db mydb
PRIMARY> var chars = "abcdefghijklmnopqrstuvwxyz";
PRIMARY> for (var i = 0; i < chars.length; i++) {
... var char = chars.substr(i, 1);
... var doc = {char:char, code:char.charCodeAt(0)};
... db.mycoll.insert(doc);
... }
PRIMARY> db.mycoll.find()
{ "_id" : ObjectId("4f44e9a44bad9102e363fca2"), "char" : "a", "code" : 97 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fca3"), "char" : "b", "code" : 98 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fca4"), "char" : "c", "code" : 99 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fca5"), "char" : "d", "code" : 100 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fca6"), "char" : "e", "code" : 101 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fca7"), "char" : "f", "code" : 102 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fca8"), "char" : "g", "code" : 103 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fca9"), "char" : "h", "code" : 104 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcaa"), "char" : "i", "code" : 105 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcab"), "char" : "j", "code" : 106 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcac"), "char" : "k", "code" : 107 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcad"), "char" : "l", "code" : 108 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcae"), "char" : "m", "code" : 109 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcaf"), "char" : "n", "code" : 110 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb0"), "char" : "o", "code" : 111 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb1"), "char" : "p", "code" : 112 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb2"), "char" : "q", "code" : 113 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb3"), "char" : "r", "code" : 114 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb4"), "char" : "s", "code" : 115 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb5"), "char" : "t", "code" : 116 }
has more
PRIMARY> it
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb6"), "char" : "u", "code" : 117 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb7"), "char" : "v", "code" : 118 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb8"), "char" : "w", "code" : 119 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb9"), "char" : "x", "code" : 120 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcba"), "char" : "y", "code" : 121 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcbb"), "char" : "z", "code" : 122 }
PRIMARY> exit
bye

セカンダリから見てみる

root@johan:~# /usr/local/mongodb/bin/mongo --port 27018
MongoDB shell version: 2.0.2
connecting to: 127.0.0.1:27018/test
SECONDARY> show dbs
local	0.125GB
mydb	0.0625GB
SECONDARY> use mydb
switched to db mydb
SECONDARY> db.getMongo().setSlaveOk()
SECONDARY> show collections
mycoll
system.indexes
SECONDARY> db.mycoll.find()
{ "_id" : ObjectId("4f44e9a44bad9102e363fca2"), "char" : "a", "code" : 97 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fca3"), "char" : "b", "code" : 98 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fca4"), "char" : "c", "code" : 99 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fca5"), "char" : "d", "code" : 100 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fca6"), "char" : "e", "code" : 101 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fca7"), "char" : "f", "code" : 102 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fca8"), "char" : "g", "code" : 103 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fca9"), "char" : "h", "code" : 104 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcaa"), "char" : "i", "code" : 105 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcab"), "char" : "j", "code" : 106 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcac"), "char" : "k", "code" : 107 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcad"), "char" : "l", "code" : 108 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcae"), "char" : "m", "code" : 109 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcaf"), "char" : "n", "code" : 110 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb0"), "char" : "o", "code" : 111 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb1"), "char" : "p", "code" : 112 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb2"), "char" : "q", "code" : 113 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb3"), "char" : "r", "code" : 114 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb4"), "char" : "s", "code" : 115 }
{ "_id" : ObjectId("4f44e9a44bad9102e363fcb5"), "char" : "t", "code" : 116 }
has more
SECONDARY> db.getMongo().slaveOk = false
false
SECONDARY> exit
bye

プライマリを停止してみる

root@johan:~# /usr/local/mongodb/bin/mongo
MongoDB shell version: 2.0.2
connecting to: test
PRIMARY> use admin
switched to db admin
PRIMARY> db.shutdownServer()
Wed Feb 22 22:22:10 DBClientCursor::init call() failed
Wed Feb 22 22:22:10 query failed : admin.$cmd { shutdown: 1.0 } to: 127.0.0.1
server should be down...
Wed Feb 22 22:22:10 trying reconnect to 127.0.0.1
Wed Feb 22 22:22:10 reconnect 127.0.0.1 ok
SECONDARY> exit
bye
root@johan:~# ps -ef | grep mongo
root      8336     1  0 21:56 ?        00:00:07 /usr/local/mongodb/bin/mongod --replSet sampleset --journal --port 27018 --logappend --logpath /data/mongo2/logs/mongod.log --pidfilepath=/data/mongo2/logs/mongod.pid --dbpath=/data/mongo2/db --fork
root      8351     1  0 21:56 ?        00:00:06 /usr/local/mongodb/bin/mongod --replSet sampleset --journal --port 27019 --logappend --logpath /data/mongo3/logs/mongod.log --pidfilepath=/data/mongo3/logs/mongod.pid --dbpath=/data/mongo3/db --fork
root      9079  5435  0 22:22 pts/0    00:00:00 grep mongo
root@johan:~# 

レプリカセットのステータスを確認してみる

root@johan:~# /usr/local/mongodb/bin/mongo --port 27018
MongoDB shell version: 2.0.2
connecting to: 127.0.0.1:27018/test
PRIMARY> rs.status()
{
	"set" : "sampleset",
	"date" : ISODate("2012-02-22T13:24:00Z"),
	"myState" : 1,
	"syncingTo" : "localhost:27017",
	"members" : [
		{
			"_id" : 0,
			"name" : "localhost:27017",
			"health" : 0,
			"state" : 8,
			"stateStr" : "(not reachable/healthy)",
			"uptime" : 0,
			"optime" : {
				"t" : 1329916324000,
				"i" : 26
			},
			"optimeDate" : ISODate("2012-02-22T13:12:04Z"),
			"lastHeartbeat" : ISODate("2012-02-22T13:22:09Z"),
			"pingMs" : 0,
			"errmsg" : "socket exception"
		},
		{
			"_id" : 1,
			"name" : "localhost:27018",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"optime" : {
				"t" : 1329916324000,
				"i" : 26
			},
			"optimeDate" : ISODate("2012-02-22T13:12:04Z"),
			"self" : true
		},
		{
			"_id" : 2,
			"name" : "localhost:27019",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 1385,
			"optime" : {
				"t" : 1329916324000,
				"i" : 26
			},
			"optimeDate" : ISODate("2012-02-22T13:12:04Z"),
			"lastHeartbeat" : ISODate("2012-02-22T13:23:59Z"),
			"pingMs" : 0
		}
	],
	"ok" : 1
}
PRIMARY> exit
bye