MongoDBにおけるレプリケーションとシャーディング -構築編2- | よしやのブログ

よしやのブログ

ブログの説明を入力します。

さて、色々忙しくなってたので日も空いてしまいましたが、クリスマスに暇なので

続きのシャーディング構築編でも書いていこうかと思います

シャーディングはレプリケーションよりずっと複雑ですので、まず登場するサーバからまとめて
行きましょう。

1 シャードクラスタ: 実際に水平分割されているDBサーバ。例えば、2000件のデータがあるとすれば、これを2つに分けてシャード1には1から1000件のデータ、シャード2には1000から2000のデータを入れる。この場合、シャードは2つとなる

2 mongosルータ: 各シャードにはデータの一部しかないため、シャード1にアクセスした場合、シャード2のデータは一切見ることはできません。これでは使いものにならないため、
何らかの別の窓口が必要になります。それがmongosです。

3 設定サーバクラスタ: シャード化がどのようになっているかは一体どこに保存されるのでしょうか? レプリケーションでは、それぞれがpingを送り合いoplogをたどることでここのレプリカが自分の立ち位置を把握していました。ではシャーディングでは、各シャードがpingを送っているのでしょうか?
これは実は違っていて、別途設定サーバを用意しています。この設定サーバからのメタデータをmongosはオンメモリに展開することで、データの振り分けをしています、
この設定のメタデータはシャーディングの心臓です。よって、完全に一貫性の取れるもので、壊れてほしくないわけです。

そこで、なんと、設定サーバをサービスで使うデータよりも強くレプリケーションを張るわけです。さらに、強いデータの一貫性を求めるので、2フェーズコミットでデータをやりとりしています。

これら3つがシャーディングのクラスタリングで必要な要素になっています。

-------------------------------------------------------------------------------------------

チャンクについて:

データのぶつ切れのことをよくチャンクとか言いますが、このシャード化されたデータもチャンクといいます。しかし、ちょっと難しいことがひとつあって、それが

シャーディングにおけるチャンクは論理的なもので、物理的なものではない

ということです。

どういうことかというと、チャンクによって、データがシャード1とシャード2に分割されているとしましょう。

データの1から200はシャード1データ201から400まではシャード2、データ401から800までがシャード1、データ801から1000までがシャード2。
こういった分け方が平気で内部で行われています。

つまり、大体2つに分けるといっても、そのデータの中点から真っ二つというわけではないということです。

それぞれぶつ切りにされ、それぞれのシャードに分散されているわけです。

チャンクはその分散の度合いを示すことになります。チャンクが多いとそれは細かくぶつ切りにされているだろうし、逆に、チャンクが2つとなるとそれはある意味直感的で、それこそ真っ二つにデータを中点から分割してそれぞれをシャードに保存しているということになります。


知っている人は知っているのですが、これはLinuxでいうLVMに似ています。論理ボリュームのことですが、

つまりは、人間が直感的に理解できるようなインターフェースを”論理的”とか言って提供しているにすぎないわけです。

----------------------------------------------------------------------------------------

更に難しい話に入りますが、このチャンク、うまいことぶつ切りにするのはいいですが、チャンクのサイズがある閾値を超えた時、そのチャンクが分割されるようになっています。それで2つに分裂したチャンクはそれぞれふさわしいシャードにまた入れなおされます。

これは完全に物理的なデータの移行です。
あとで、この辺りの難しさみたいなのを解説しようと思います。
----------------------------------------------------------------------------------------

さて、長々と書いたのですが、いよいよシャードクラスタを構築してみます。

まず、データの格納先を作っておきます シャードサーバは2つを想定、環境とIP等々は
資源の問題からローカルだけでやります。構築編1を参照。
http://ameblo.jp/myon53/entry-11721776063.html


$ mkdir /data/rs-a
$ mkdir /data/rs-b

次にシャードサーバを起動します

$ mongod --shardsvr shard-a --dbpath /data/rs-a --port 30000 --logpath /data/rs-a.log --fork --nojournal

$ mongod --shardsvr shard-b --dbpath /data/rs-b --port 30001 --logpath /data/rs-b.log --fork --nojournal

それぞれのオプションはレプリカ構築の時と意味は大体同じです。
ただ、今回はshardsvr がついてますが、これがシャードとして動作させるという意味です。


次にメタデータを保存する設定サーバを作ります。

やはり、設定を保存するパスも必要ですので

$ mkdir /data/config-1
$ mkdir /data/config-2

$ mongod --configsvr --dbopath /data/config-1 --port 27019 --logpath /data/config-1.log --fork --nojournal

$ mongod --configsvr --dbopath /data/config-2 --port 27020 --logpath /data/config-2.log --fork --nojournal

意味はかんたんですね。設定サーバとして動作させる--configオプションがついただけです。

最後にmongosを起動します。

$ mongos --configdb 127.0.0.1:27019,127.0.0.1:27020 --logpath /data/mongos.log --fork --port 40000

これも意味は簡単です。設定サーバをさっき立てた2つを指定してmongosを起動するという意味です。ポートは他とかぶらなければ何でも大丈夫です。
試してないですが、127.0.0.1はlocalhostでも大丈夫でしょう。またはetc/hostsとかに解決できる名前であれば何でもいい気がします。
ただし、解決できない名前書くと多分またunknownになる気がする。


さて、これでサーバは出揃ったのでいよいよ設定を始めますが、

実はmongoシェルにはこれらを簡単にやるヘルパ関数が出揃っています。ので、それを使います。

$ mongo 127.0.0.1:40000

> sh.addShard("shard-a/127.0.0.1:30000")
("shardAdded" : "shard-a", "ok" : 1)

> sh.addShard("shard-b/127.0.0.1:30001")
("shardAdded" : "shard-b", "ok" : 1)

こうなれば成功ですね。

作業の結果を確認する場合は

> db.getSiblingDB("config").shards.find()


さて、シャーディングを起動しましょう。このアプリケーションでのデータベース名を自分で決めてください。適当にここではyoshiyaとすると

> sh.enableSharding("yoshiya")

となります

さて、ここからが難しいところです。シャードキーを定義するのですが、それにはコレクション名が必要ですね。
さっき自分で作ったデータベースに適当にコレクションを追加して、データを入れてみてください。
ここでは、こんなのを想定します。

db : yoshiya
collection : sample
doc : {id : 1, name : "hoge"}

シャードキーの割り当ては実は複合シャードキーが使えます。これは複合インデックスと全く同じ気分でも多分大丈夫です。自分はそう思ってます。

> sh.shardCollection("yoshiya.sample", {name : 1, id : 1})

複合インデックスと同じというぐらいなのだから実はインデックス調べると表示されます。

>mongo 127.0.0.1:30000
>use yoshiya
>db.sample.getIndexes()

すると想像どおり、なんかキーが張り付いてるのが確認できると思います。

さて、今回は一旦構築までできたのでここでお話を切りたいと思います。