概要
MongoDBでシャーディングを構築します。
MongoDBのインストールですでにインストールしている前提で進めます。
環境
- Ubuntu 14.04
- MongoDB 2.6.7
今回は1台でポートを別にして複数プロセスで構築します。
configサーバは1 or 3台必要(2だとサポート外で怒られます)なので、単一障害点とならないよう今回は3つにします。
| 名前 | 役割 | 今回使用するport |
|---|---|---|
| mongos | ルーティング | 20000 |
| config0 | シャーディングのメタデータを管理 | 30000 |
| config1 | 同上 | 30001 |
| config2 | 同上 | 30002 |
| node0 | シャード | 40000 |
| node1 | 同上 | 40001 |
| node2 | 同上 | 40002 |
各プロセスの起動
デフォルトのプロセスを停止
$ sudo service mongod stop
ディレクトリ用意
複数プロセスで起動するのでデータの保存先を変えるためディレクトリを作成します。
# cd /var/lib/mongodb # mkdir config0 # mkdir config1 # mkdir config2 # mkdir node0 # mkdir node1 # mkdir node2
configサーバ起動
--configsvrオプションをつけるとconfigサーバとして起動します。forkをつけてバックグラウンドで動くようにします。
# mongod --configsvr --port 30000 --dbpath /var/lib/mongodb/config0 --logpath /var/log/mongodb/config0.log --fork # mongod --configsvr --port 30001 --dbpath /var/lib/mongodb/config1 --logpath /var/log/mongodb/config1.log --fork # mongod --configsvr --port 30002 --dbpath /var/lib/mongodb/config2 --logpath /var/log/mongodb/config2.log --fork
mongosサーバ起動
さきほどのconfigサーバをlocalhost:30000,localhost:30001,localhost:30002といったカンマ区切りで指定します。
# mongos --configdb localhost:30000,localhost:30001,localhost:30002 --port 20000 --logpath /var/log/mongodb/mongos.log --chunkSize 1 --fork
チャンクサイズはデフォルトでは64Mですが、今回はチャンクが分割される動作を確認したいために小さい1MBに設定します。
mongodサーバ起動
--shardsvrオプションをつけます。
# mongod --shardsvr --port 40000 --dbpath /var/lib/mongodb/node0 --logpath /var/log/mongodb/node0.log --fork # mongod --shardsvr --port 40001 --dbpath /var/lib/mongodb/node1 --logpath /var/log/mongodb/node1.log --fork # mongod --shardsvr --port 40002 --dbpath /var/lib/mongodb/node2 --logpath /var/log/mongodb/node2.log --fork
動作確認
以下のようにプロセスがあればOKです。
# ps x | grep mongo 16969 ? Sl 0:02 mongod --configsvr --port 30000 --dbpath /var/lib/mongodb/config0 --logpath /var/log/mongodb/config0.log --fork 16995 ? Sl 0:02 mongod --configsvr --port 30001 --dbpath /var/lib/mongodb/config1 --logpath /var/log/mongodb/config1.log --fork 17015 ? Sl 0:00 mongod --configsvr --port 30002 --dbpath /var/lib/mongodb/config2 --logpath /var/log/mongodb/config2.log --fork 17029 ? Sl 0:00 mongos --configdb localhost:30000,localhost:30001,localhost:30002 --port 20000 --logpath /var/log/mongodb/mongos.log --chunkSize 1 --fork 17091 ? Sl 0:00 mongod --shardsvr --port 40000 --dbpath /var/lib/mongodb/node0 --logpath /var/log/mongodb/node0.log --fork 17104 ? Sl 0:00 mongod --shardsvr --port 40001 --dbpath /var/lib/mongodb/node1 --logpath /var/log/mongodb/node1.log --fork 17117 ? Sl 0:00 mongod --shardsvr --port 40002 --dbpath /var/lib/mongodb/node2 --logpath /var/log/mongodb/node2.log --fork
シャーディング
シャードの追加
mongosサーバにシャードを追加していきます。
$ mongo localhost:20000
mongosサーバに入り、
mongos> sh.addShard("localhost:40000")
{ "shardAdded" : "shard0000", "ok" : 1 }
mongos> sh.addShard("localhost:40001")
{ "shardAdded" : "shard0000", "ok" : 1 }
mongos> sh.addShard("localhost:40002")
{ "shardAdded" : "shard0000", "ok" : 1 }
各シャードを追加します。
今回はすべて同じサーバなので問題無いですが、複数台使う際はlocalhostと別のFQDNを混ぜて使わないでください。エラーが起きます。
確認してみます。
mongos> sh.status()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"version" : 4,
"minCompatibleVersion" : 4,
"currentVersion" : 5,
"clusterId" : ObjectId("54e73fa06ae061cf73d0d5a8")
}
shards:
{ "_id" : "shard0000", "host" : "localhost:40000" }
{ "_id" : "shard0001", "host" : "localhost:40001" }
{ "_id" : "shard0002", "host" : "localhost:40002" }
大丈夫そうですね。
シャーディングの有効化
logdbというDBに対してシャーディングを有効化しましょう。
mongos> sh.enableSharding("logdb")
{ "ok" : 1 }
シャードキーの設定
次にコレクションに対してシャードキーの設定をします。
usersというコレクションの_idフィールドに設定することにします。
mongos> sh.shardCollection("logdb.users", {"_id": 1})
{ "collectionsharded" : "logdb.users", "ok" : 1 }
シャードキーの注意点
今回は_idをキーにしていますが、実際に運用する際は以下のことに注意してください。
- 適切にバランシングできるよう、シャードキーはランダムな値が望ましい。
- 一度シャードキーを設定したら変更はできない。
- すでにデータが入っているコレクションに対してシャーディングを設定する場合、シャードキーはインデックスをつけている必要がある。
- シャードキーに設定したフィールドは値をupdateできない。する場合一度removeしてinsertする必要がある。
- findAndModifyではシャードキーをクエリに含めなければいけない
- update()で
multi: trueの場合、シャードキーをクエリに含めなければいけない
動作確認
ダミーデータを入れてみます。_idは自動でつくので、適当なデータを入れます。
mongos > use logdb
mongos > for (var i = 1; i <= 100000; i++) {
db.users.insert({ number: i , name: "foo"+i})
}
ステータスを確認してみます。
mongos> sh.status()
--- Sharding Status ---
shards:
{ "_id" : "shard0000", "host" : "localhost:40000" }
{ "_id" : "shard0001", "host" : "localhost:40001" }
{ "_id" : "shard0002", "host" : "localhost:40002" }
databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "test", "partitioned" : false, "primary" : "shard0000" }
{ "_id" : "logdb", "partitioned" : true, "primary" : "shard0000" }
logdb.users
shard key: { "_id" : 1 }
chunks:
shard0002 4
shard0000 4
shard0001 4
チャンクがちゃんと等分されていますね。シャーディングができている証拠です。
一応直接各ノードのDBにアクセスして確認してみましょう。
node0
$ mongo localhost:40000 > use logdb > db.users.count() 35751
node1
$ mongo localhost:40001 > use logdb > db.users.count() 42987
node2
$ mongo localhost:40002 > use logdb > db.users.count() 21262
合計すると挿入した10万ドキュメントになります。
以上です。お疲れ様でした。