通常のRWはMasterで行われ、Slaveはホットスタンバイとなる。
Ver 1.6の頃までメジャーなReplicationで、RWをMasterのみで
行うので高い一貫性が実現される
Master / Slave(+ arbiter)で構成される。
Masterに問題が発生すると、Slaveのうちの1台がMasterに自動昇格する。
ただし、Slaveが昇格するためにはMaster以外の過半数の投票が必要。
例)Master 1台 / Slave 1台 でMasterがコケた時、Slaveが自分に
投票しても1/2で過半数にならないので、昇格できない。
⇒Slaveを追加する、又は、arbiter(決裁者)を追加する。
arbiter(決裁者):データを保持せずに、決裁権のみもったサーバ
データファイルを丸ごとコピーする方法で、バックアップ作業自体は
簡単だが、書き込み中には(安全に)行えないため、サービス停止
の必要がある。
mysqldumpなどと同様に、サービス運用中のデータを専用コマンドで
エクスポートする。また、インポートも可能。
mongodump –host localhost:27020 –db mydb –out /data/mongo/dump
mongorestore –port 27021 –db mydb –drop –dbpath /data/mongo/dump
Sahrdingには、データを分散するサーバ(mongod)以外に、アプリからの
窓口になる「Mongs Server(mongos)」、分散状況を管理する
「Config Server(mongoc)」が必要となる。
また、分散の1系統が止まるとデータにアクセスできなくなるので、
分散サーバのバックアップ(Slave)が必要となる。
パフォーマンスについて、運用事例からみると、大量の読み込みに
パフォーマンスを発揮するようで、そういった環境に採用されている
ことはあるが、インターネット上で確認される多くのMongoDBの採用事例では
Replica Setsのみで、Shardingの採用はあまり見られない。
● 64bit
32bit環境でMongoDBを構築した場合、DBファイルのサイズは32bitの制限で
2.5GBまでしか拡張できない。
そこそこの規模の環境ではすぐに頭打ちになるので、公式では64bit環境を
推奨している
● ext4
MongoDB はデータ保存用の領域を先取り(preallocates)する仕組みがあるが、
この処理はext3ではパフォーマンスが悪い。
ext4では快適に動作する。
● 更新系の処理のレスポンスはリアルタイムではない
アプリから更新系の処理を投げて、直後に取得しても取得できないことがある。
更新系の処理はサーバに届いた時点でレスポンスが変えるので、実際には
サーバで処理待ちの場合がある。
● Replica Setsの同期が不完全な場合がある
Replicationは、Masterで行われた更新ログをoplogというコレクションに
保存し、SlaveはMasterのoplogを取得、自分に実行することで同期している。
長期的な運用によってoplogの古い内容が削除された環境にSlaveを追加
するなどした場合、削除された更新内容は取り戻せないので、不整合が
発生する。
そういった場合は、dump&resotreで同期させてから追加するなどの
方法をとらないといけない。
oplogのデフォルトサイズは、64bitマシーンではディスクスペースの5%(ただし
1GBは最小限必要)が、32bitマシンでは50MBが設定。
oplogのサイズは起動時のオプションでサイズ変更可能。
i.g. –oplogSize 500
oplogのサイズ確認
> use local
> db.oplog.rs.stats()
● メモリ>物理メモリ=パフォーマンス低下
ワーキングセット(ドキュメントの取り扱い単位=頻繁にRWされるデータ群)
が物理メモリの容量を超えるとDiskIOが発生し、パフォーマンスが低下する。
● サーバで大切なのは、DiskIOとメモリ容量
MongoDBはマルチコアを有効に活用できない。
RW時にはロックが掛るので、IOの速度を上げる、データをメモリに乗せる、
などがパフォーマンス改善につながる。
一つの指標として、db.stats()で表示されるindexSizeが必要メモリの目安。
● 自動Sharding
デフォルト200MBのchunkがいっぱいになると、そのchunkが分裂する。
データが大量に入ってきている時は、常に細胞分裂している状況になる。
起動時のオプションでサイズ変更可能。
i.g. –chunkSize 500
● 自動Balancing
chunk(データの塊り)がクラスタ間で偏ったときに、自動的に他のクラスタへ
移動する仕組み。
動作中も通常操作は行えるが、一度メモリに乗せてから移動するためにパフォー
マンスの低下、移動中はcountで対象が移動元移動先2重にカウントされる、
など弊害もある。
また、chunkサイズが空きメモリに乗らなければ自動で移動されない。
自動Balancingをオフにすることも可能
> use config
> db.settings.update( { _id: “balancer” }, { $set : { stopped: true } } , true )
chunkの手動移動
> db.runCommand( { moveChunk : “test.blog.posts” ,
…. find : { author : “eliot” } ,
…. to : “shard1” } )
movechunk: データベース名を含む、完全なコレクションの名前空間を指定します。
find: 移動すべきchunkを特定するクエリーを記述します。このコマンドは自動的に移動元(ドナー)となるshardを見つけてくれるでしょう。
to: chunkの移動先となるshardIDを指定します。
● sharding環境のバックアップはひと手間
1.mongos経由でAutoBalancingをOff
2.各Replica Setsにfsync lock
3.各mongodにmongodumpを実行
4.各Replica Setsにfsync unlock
5.mongos経由でAutoBalancingをOn
● shardの追加タイミング
公式に閾値の目安などは見られないが、以下のようなコメントはある。
> 覚えておく必要のある重要なことは、一度容量の限界に到達したとき、
> オブジェクトが小さいと停止時間を発生させずに新たに容量を追加するのは難しいということです。
> しかし、事前に容量の限界にきていることを事前に察知できれば、停止時間なしで稼働中のシステムに
> シャードを追加することができます。
mongoDBのパフォーマンス低下は突然やってくるので、常に監視を行っておく。