MongoDBでゆるふわDB体験

第6回 レプリケーション+シャーディングでMongoDBをもっと使いこなす

この記事を読むのに必要な時間:およそ 4 分

シャーディングの設定

いよいよ,レプリカセットをシャードサーバに割り当てて,シャーディングを構成していきます。まずフロントサーバにて,configサーバとmongosを起動します。この手順は前回の記事の手順と同じですので,詳しい解説は前回をご覧ください。

フロントサーバでの作業

mkdir data/config
bin/mongod --configsvr --port 20001 --dbpath data/config --logpath=log/config --nojournal --fork
bin/mongos --configdb (フロントサーバのIP):20001 --port 20000 --logpath=log/mongos --chunkSize 1 --fork
[注意]
チャンクサイズを1に設定しているのは,シャーディングの動作を確認しやすくするためです。実運用ではシステムの要件に合わせた値に設定してください。

続いて,mongosサーバにmongoシェルで接続して,シャードサーバを追加してきます。mongodを単体で登録する場合とは違い,レプリカセットを登録します。

フロントサーバでの作業

bin/mongo localhost:20000/admin

フロントサーバのmongoシェルでの作業

sh.addShard("rs0/(サーバAのIP):30000,(サーバBのIP):30001,(サーバCのIP):30002")   
{ "shardAdded" : "rs0", "ok" : 1 }

sh.addShard("rs1/(サーバAのIP):30010,(サーバBのIP):30011,(サーバCのIP):30012")   
{ "shardAdded" : "rs1", "ok" : 1 }

sh.addShard("rs2/(サーバAのIP):30020,(サーバBのIP):30021,(サーバCのIP):30022")   
{ "shardAdded" : "rs2", "ok" : 1 }

確認

sh.status()
--- Sharding Status ---
  sharding version: { "_id" : 1, "version" : 3 }
  shards:
        {  "_id" : "rs0",  "host" : "rs0/(サーバAのIP):30000,(サーバBのIP):30001,(サーバCのIP):30002" }
        {  "_id" : "rs1",  "host" : "rs1/(サーバAのIP):30010,(サーバBのIP):30011,(サーバCのIP):30012" }
        {  "_id" : "rs2",  "host" : "rs2/(サーバAのIP):30020,(サーバBのIP):30021,(サーバCのIP):30022" }
  databases:
        {  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }

最後にデータを投入し,そのデータに対してシャーディングを有効にします。この手順も前回の記事の手順と同じです。

フロントサーバのmongoシェルでの作業

use logdb

データ投入

for(var i=1; i<=100000; i++) db.logs.insert({"uid":i, "value":Math.floor(Math.random()*100000+1)})

データ投入の確認

db.logs.count();

インデックス作成

db.logs.ensureIndex( { uid : 1 } );

admin DBに切り替え

use admin

シャーディングの有効化

sh.enableSharding("logdb")
sh.shardCollection("logdb.logs" , { uid : 1 })

確認

sh.status()

次は実際にサーバ障害を発生させ,挙動を観察します。

障害時の動作実験

これまでの作業で,シャーディング構成はできていますが,ここでは障害を発生させ,処理を続けられるか確認します。

図4

図4

まず,以下のコマンドによりクライアント相当の簡単なプログラムを動かします。

フロントサーバでの作業

watch "bin/mongo localhost:20000/logdb --eval 'db.logs.count() ;'"

このコマンドは2秒に1回logdbデータベースのlogsコレクション数をカウントしているので,ずっと10000が表示されているはずです。このコマンドはmongoシェルの--evalオプションを用いて,DBの中身をカウントするコマンドを実行し,それをwatchコマンドにより2秒に1回実行しています。

この状態でサーバCの障害を想定して,サーバCのmongodをすべて落としてください(より本格的にやりたい人はサーバCの電源を落としても良いですw⁠⁠。

サーバCでの作業

killall mongod

するとどうでしょうか? フロントサーバのdb.logs.count()コマンドは,フェイルオーバー中は失敗するもの,数秒のうちにフェイルオーバーが完了し,その後は成功すると思います。現時点でのシステムの状態を確認してみましょう。

まずシャーディングの状況ですが,以下のコマンドで確認します。

フロントサーバでの作業

bin/mongo localhost:20000/admin
sh.status()

見てわかるように,シャーディングの状況は何ひとつ変わっていません。mongosからはレプリカセットしか管理していないため,各mongodの状態までは管理していません。

続いてレプリカセットの状況確認です。

サーバAでの作業

bin/mongo localhost:30020  # →rs2のmongodにログイン
rs.status()

おそらく,サーバAかサーバBのどちらかがプライマリになっていると思います。また,サーバCは"(not reachable/healthy)"と表示されていると思います。

次回のテーマ

今回はレプリケーションとシャーディングを組み合わせた構成について紹介しました。本構成を用いることで,可用性と読み取り性能を両方向上させることができます。

次回の記事ではMonogoDBでサイズの大きなファイルを扱う機能である,GridFSについて紹介する予定です。

著者プロフィール

藤崎祥見(ふじさきしょうけん)

野村総合研究所 OpenStandia所属。オープンソースのR&Dとセミナー講師を担当。

Debian,Ubuntu,Liferayのコミュニティで活動した後,MongoDBの翻訳に関わり,丸の内MongoDB勉強会を始める。

実家がお寺で,住職の資格を所持する坊主系エンジニア。

Twitter:@syokenz


渡部徹太郎(わたなべてつたろう)

野村総合研究所 OpenStandia所属。オープンソースを使ったSIやサポートの業務に従事。

藤崎と共同で丸の内MongoDB勉強会を始める。

趣味は自宅サーバ。好きなものはLinuxとRuby。

Twitter:@fetarodc


林田敦(はやしだあつし)

野村総合研究所 OpenStandia所属。オープンソースを使ったSIや製品開発業務に従事。

丸の内MongoDB勉強会では広報兼雑用係を務める。

趣味はレザークラフト,ダイビング,スキー,キャンプ,ジェットスキー,カメラ等々。作って滑って撮って潜れるエンジニア。

Facebook:Atsushi Hayashida