概要
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万ドキュメントになります。
以上です。お疲れ様でした。