notebook

都内でWEB系エンジニアやってます。

mongoDBのクラスタ環境をいじってみる

今回は業務で扱う必要が出てきてしまったため急場しのぎですがmongoDBをやっていきます

いきなりシャーディング+レプリカセットとかいろんな概念が一気に入ってくるとわからなくなってしまいそうなので一つづつ理解していくようにしていく

また、各種ノードに関してローカルのサーバでポートを変えればいくらでもノードを立ち上げることができたので一台のVMで複数mongodを立ち上げることで試す

前提

大きく分けて下記三つの役割がある

mongos

クエリのルーティングなどを行う クライアント側のアプリケーションが接続を行うのはこのサーバ

mongod

シャードやレプリカセットを構成要素となるサーバ(ノード)

mongos,mongod(configserver)がない場合でも機能する(ローカルとか)

mongod(configserver)

各種設定やメタデータ(shardの設定やロックの情報などを管理)を扱っている

冗長化のためにレプリカセットを組んでおくのが基本

シャーディングを試す

下記と公式を参考にしました

MongoDBのSharding機能で遊ぶ - 個人的なまとめ

hachi.hatenablog.com

  • コマンドについては下記

MongoDBのデータ構造な簡単な操作など - Qiita

qiita.com

構成

  • config
    • 1台
  • mongos
    • 1台
  • shard
    • 3台

f:id:swfz:20161115033636p:plain

configサーバ

mkdir /data/mongo/config
mongod --configsvr --port 27030 --dbpath=/data/mongo/config --logpath /data/mongo/config/log --fork

mongosの起動

mongos --port 27017 --configdb localhost:27030 --chunkSize 1 --logpath /data/mongo/mongos/log --fork

各シャードの起動

mkdir /data/mongo/shard1
mkdir /data/mongo/shard2
mkdir /data/mongo/shard3

mongod --port 27021 --dbpath=/data/mongo/shard1
mongod --port 27022 --dbpath=/data/mongo/shard2
mongod --port 27023 --dbpath=/data/mongo/shard3

シャードの追加

  • mongos
use admin
db.runCommand({"addShard":"localhost:27021"})
db.runCommand({"addShard":"localhost:27022"})
db.runCommand({"addShard":"localhost:27023"})
  • シャードの確認

どちらでも同じ出力

> db.printShardingStatus()
> sh.status()
--- Sharding Status ---
  sharding version: {
        "_id" : 1,
        "minCompatibleVersion" : 5,
        "currentVersion" : 6,
        "clusterId" : ObjectId("580c68b71fc6c85737ab8492")
}
  shards:
        {  "_id" : "shard0000",  "host" : "localhost:27021" }
        {  "_id" : "shard0001",  "host" : "localhost:27022" }
        {  "_id" : "shard0002",  "host" : "localhost:27023" }
  active mongoses:
        "3.2.7" : 1
  balancer:
        Currently enabled:  yes
        Currently running:  no
        Failed balancer rounds in last 5 attempts:  0
        Migration Results for the last 24 hours:
                No recent migrations
  databases:

データを入れてみる

mongo localhost:27017
> use sample # 自動でDB生成
> db.sample.insert({ category: "A", name: "aaaaaaaaaaa", age: 25 })
> db.sample.insert({ category: "B", name: "bbbbbbbbbbb", age: 35 })
> db.sample.insert({ category: "C", name: "ccccccccccc", age: 45 })
  • 確認
> db.sample.find()
{ "_id" : ObjectId("580c701a8d3072138e3e8ef2"), "category" : "A", "name" : "aaaaaaaaaaa", "age" : 25 }
{ "_id" : ObjectId("580c7129526e856a60bb2113"), "category" : "B", "name" : "bbbbbbbbbbb", "age" : 35 }
{ "_id" : ObjectId("580c7151526e856a60bb2114"), "category" : "C", "name" : "ccccccccccc", "age" : 45 }
  • 各シャードで確認してみる
$ mongo localhost:27021
> use sample
> db.sample.find()
{ "_id" : ObjectId("580c701a8d3072138e3e8ef2"), "category" : "A", "name" : "aaaaaaaaaaa", "age" : 25 }
{ "_id" : ObjectId("580c7129526e856a60bb2113"), "category" : "B", "name" : "bbbbbbbbbbb", "age" : 35 }
{ "_id" : ObjectId("580c7151526e856a60bb2114"), "category" : "C", "name" : "ccccccccccc", "age" : 45 }
$ mongo localhost:27022
> use sample
> db.sample.find()
$ mongo localhost:27023
> use sample
> db.sample.find()

シャード設定

DB単位,Collection単位でシャード設定しないといけない模様

新たにshsampleというDBにstats_aというcollectionを追加する

# DB,Collection二つ一遍に設定できるかと思ったら駄目だった
mongos> sh.shardCollection("shsample.stats_a",{"id": 1});
{ "ok" : 0, "errmsg" : "sharding not enabled for db shsample", "code" : 20 }

# シャード設定を追加する
mongos> use admin
switched to db admin
mongos> db.runCommand({ enablesharding: "shsample"});
{ "ok" : 1 }

# shsample に対してシャーディング設定をする( 渡すのはshard key) 複数も可能
sh.shardCollection("shsample.stats_a",{"id": 1})
  • データを追加してみる
> db.stats_a.insert({ id: 1, name: "hoge" })
> db.stats_a.insert({ id: 2, name: "fuga" })
> db.stats_a.insert({ id: 3, name: "piyo" })
use shsample
> db.stats_a.find()

変わってなかった。。。

そもそもchunksizeがバランシングの最小単位なので割と多めのデータを入れないといけない

今回の場合だと1Mですね(chunksize)

ファイルからデータをインポート

MongoDBのmongoimportでハマった:変なJSON形式 - 檜山正幸のキマイラ飼育記

d.hatena.ne.jp

ここを参考にログを入れてみる

テキストの1行に1個のJSONオブジェクトとのことなのでfluentdとかで出力したログファイルがちょうどよさそう

適当なログをさらってきて突っ込んでみます

$ mongoimport --port 27017 --db shsample --collection stats_a --type json --file sample.log

データを登録したので確認してみる

> sh.status()
....
  databases:
        {  "_id" : "sample",  "primary" : "shard0000",  "partitioned" : false }
        {  "_id" : "test",  "primary" : "shard0001",  "partitioned" : false }
        {  "_id" : "shsample",  "primary" : "shard0002",  "partitioned" : true }
                shsample.stats_a
                        shard key: { "id" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                shard0000       28
                                shard0001       27
                                shard0002       153
                        too many chunks to print, use verbose if you want to force print

各シャードに分散されたようです

  • 各シャードの件数を確認する
$ mongo localhost:27021/shsample
> db.stats_a.count()
18790

$ mongo localhost:27022/shsample
> db.stats_a.count()
19673

$ mongo localhost:27023/shsample
> db.stats_a.count()
18937
  • mongosから問い合わせる
$ mongo localhost:27017
mongos> db.stats_a.count()
57400

件数もぴったり合いました

mongodbの特性として各シャード一つ一つが独立したDBとして動作可能という特性がある模様

mongosが各シャードに対してクエリを発行してまとめているという感じでしょうか

shardingに関してはなんとなく概要がつかめた