mongodbでシャーディングしてみる

# 準備
EC2で4台構成で試す。
mongoのバージョンは3.2.9
core1, db1, db2, db3の構成
core1ではconfigサーバとmongosサーバを起動する。

```
wget http://downloads.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.2.9.tgz
```

# confの設定とmongodの起動(db1,db2,db3)

```
[root@db1 mongodb]# cat conf/shard.conf 
port = 27011
dbpath = /root/mongodb/data/shard
fork = true
shardsvr = true
logpath = /root/mongodb/logs/mongo.log
logappend = yes
smallfiles = true
storageEngine = wiredTiger
```

起動

```
[root@db2 mongodb]# ./bin/mongod -f conf/shard.conf
```



# configサーバとmongosの起動(core1)
configサーバはshardクラスタのメタデータを保持するためのサーバ。
mongosサーバはshardを構成するmongodへのルーターとなる。実データは保持しない。


configサーバの起動

```
[root@core1 mongodb]# cat conf/config.conf                                                                                                       
port = 27001
dbpath = /root/mongodb/data/configdb
fork = true
configsvr = true
logpath = /root/mongodb/logs/mongolog.log
logappend = yes
smallfiles = true

[root@core1 mongodb]# ./bin/mongod -f conf/config.conf                                                                                           
```

mongosサーバの起動
ポートのaclを忘れないように。

```
[root@core1 mongodb]# cat conf/mongos.conf 
port = 27000
configdb = core1:27001
chunkSize = 1
fork = true
logpath = /root/mongodb/logs/shard.log
logappend = yes

[root@core1 mongodb]# ./bin/mongos -f conf/mongos.conf 

[root@core1 mongodb]# pgrep -lf mongo
3190 ./bin/mongod -f conf/config.conf
3212 ./bin/mongos -f conf/mongos.conf
```

# mongosサーバにシャーディングの設定

## クラスタに追加

```
[root@core1 mongodb]# ./bin/mongo --port 27000                                                                           
MongoDB shell version: 3.2.9
connecting to: 127.0.0.1:27000/test
mongos> sh.status()                                                                                                      
--- Sharding Status --- 
  sharding version: {
        "_id" : 1,
        "minCompatibleVersion" : 5,
        "currentVersion" : 6,
        "clusterId" : ObjectId("588dc5bf70cae5b0591f0d45")
}
  shards:
  active mongoses:
        "3.2.9" : 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:

mongos> sh.addShard("db1:27011")                                                                                         
{ "shardAdded" : "shard0000", "ok" : 1 }
mongos> sh.addShard("db2:27011")                                                                                         
{ "shardAdded" : "shard0001", "ok" : 1 }
mongos> sh.addShard("db3:27011")                                                                                         
{ "shardAdded" : "shard0002", "ok" : 1 }
mongos> sh.status()                                                                                                      
--- Sharding Status --- 
  sharding version: {
        "_id" : 1,
        "minCompatibleVersion" : 5,
        "currentVersion" : 6,
        "clusterId" : ObjectId("588dc5bf70cae5b0591f0d45")
}
  shards:
        {  "_id" : "shard0000",  "host" : "db1:27011" }
        {  "_id" : "shard0001",  "host" : "db2:27011" }
        {  "_id" : "shard0002",  "host" : "db3:27011" }
  active mongoses:
        "3.2.9" : 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:

```

## データの投入

mongos経由でデータを投入する

```
mongos> use logdb                                                                                                        
switched to db logdb
mongos> for(var i=1; i<=100000; i++)db.logs.insert({"uid":i, "value":Math.floor(Math.random()*100000+1)})                
WriteResult({ "nInserted" : 1 })
mongos> db.logs.count()                                                                                                  
100000
```

# インデックスを設定しシャーディングを実行する

```
mongos> db.logs.ensureIndex({uid:1});                                                                                    
{
        "raw" : {
                "db1:27011" : {
                        "createdCollectionAutomatically" : false,
                        "numIndexesBefore" : 1,
                        "numIndexesAfter" : 2,
                        "ok" : 1
                }
        },
        "ok" : 1
}
```

chunkを数えるとまだシャーディングが実行されていないことがわかる。

```
mongos> use config                                                                                                       
switched to db config
mongos> show collections                                                                                                 
changelog
chunks
databases
lockpings
locks
mongos
settings
shards
tags
version
mongos> db.chunks.count()                                                                                                
0
```

シャーディングを実行し確認する

```
[root@core1 mongodb]# ./bin/mongo --port 27000
MongoDB shell version: 3.2.9
connecting to: 127.0.0.1:27000/test
mongos> sh.enableSharding("logdb")                                                                                       
{ "ok" : 1 }
mongos> sh.shardCollection("logdb.logs", {uid:1})                                                                        
{ "collectionsharded" : "logdb.logs", "ok" : 1 }

mongos> sh.status()                                                                                                      
--- Sharding Status --- 
  sharding version: {
        "_id" : 1,
        "minCompatibleVersion" : 5,
        "currentVersion" : 6,
        "clusterId" : ObjectId("588dc5bf70cae5b0591f0d45")
}
  shards:
        {  "_id" : "shard0000",  "host" : "db1:27011" }
        {  "_id" : "shard0001",  "host" : "db2:27011" }
        {  "_id" : "shard0002",  "host" : "db3:27011" }
  active mongoses:
        "3.2.9" : 1
  balancer:
        Currently enabled:  yes
        Currently running:  no
        Failed balancer rounds in last 5 attempts:  0
        Migration Results for the last 24 hours: 
                6 : Success
  databases:
        {  "_id" : "logdb",  "primary" : "shard0000",  "partitioned" : true }
                logdb.logs
                        shard key: { "uid" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                shard0000       4
                                shard0001       3
                                shard0002       3
                        { "uid" : { "$minKey" : 1 } } -->> { "uid" : 10486 } on : shard0001 Timestamp(2, 0) 
                        { "uid" : 10486 } -->> { "uid" : 20972 } on : shard0002 Timestamp(3, 0) 
                        { "uid" : 20972 } -->> { "uid" : 31458 } on : shard0001 Timestamp(4, 0) 
                        { "uid" : 31458 } -->> { "uid" : 41944 } on : shard0002 Timestamp(5, 0) 
                        { "uid" : 41944 } -->> { "uid" : 52430 } on : shard0001 Timestamp(6, 0) 
                        { "uid" : 52430 } -->> { "uid" : 62916 } on : shard0002 Timestamp(7, 0) 
                        { "uid" : 62916 } -->> { "uid" : 73402 } on : shard0000 Timestamp(7, 1) 
                        { "uid" : 73402 } -->> { "uid" : 83888 } on : shard0000 Timestamp(1, 7) 
                        { "uid" : 83888 } -->> { "uid" : 94374 } on : shard0000 Timestamp(1, 8) 
                        { "uid" : 94374 } -->> { "uid" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 9) 

mongos> use config                                                                                                       
switched to db config
mongos> db.chunks.count()                                                                                                
10
```

さらに追加する

```
mongos> db.logs.insert({"uid": 100001, "value":100001})                                                                  
WriteResult({ "nInserted" : 1 })
mongos> for (var i=200000; i<250000; i++)db.logs.insert({"uid": i, "value":100001})                                      
WriteResult({ "nInserted" : 1 })
mongos> db.logs.count()                                                                                                  
150001
mongos> sh.status()                                                                                                      
--- Sharding Status --- 
  sharding version: {
        "_id" : 1,
        "minCompatibleVersion" : 5,
        "currentVersion" : 6,
        "clusterId" : ObjectId("588dc5bf70cae5b0591f0d45")
}
  shards:
        {  "_id" : "shard0000",  "host" : "db1:27011" }
        {  "_id" : "shard0001",  "host" : "db2:27011" }
        {  "_id" : "shard0002",  "host" : "db3:27011" }
  active mongoses:
        "3.2.9" : 1
  balancer:
        Currently enabled:  yes
        Currently running:  no
        Failed balancer rounds in last 5 attempts:  0
        Migration Results for the last 24 hours: 
                9 : Success
  databases:
        {  "_id" : "logdb",  "primary" : "shard0000",  "partitioned" : true }
                logdb.logs
                        shard key: { "uid" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                shard0000       5
                                shard0001       5
                                shard0002       4
                        { "uid" : { "$minKey" : 1 } } -->> { "uid" : 10486 } on : shard0001 Timestamp(10, 1) 
                        { "uid" : 10486 } -->> { "uid" : 20972 } on : shard0002 Timestamp(3, 0) 
                        { "uid" : 20972 } -->> { "uid" : 31458 } on : shard0001 Timestamp(4, 0) 
                        { "uid" : 31458 } -->> { "uid" : 41944 } on : shard0002 Timestamp(5, 0) 
                        { "uid" : 41944 } -->> { "uid" : 52430 } on : shard0001 Timestamp(6, 0) 
                        { "uid" : 52430 } -->> { "uid" : 62916 } on : shard0002 Timestamp(7, 0) 
                        { "uid" : 62916 } -->> { "uid" : 73402 } on : shard0002 Timestamp(9, 0) 
                        { "uid" : 73402 } -->> { "uid" : 83888 } on : shard0000 Timestamp(9, 1) 
                        { "uid" : 83888 } -->> { "uid" : 94374 } on : shard0000 Timestamp(1, 8) 
                        { "uid" : 94374 } -->> { "uid" : 204857 } on : shard0000 Timestamp(7, 2) 
                        { "uid" : 204857 } -->> { "uid" : 218713 } on : shard0000 Timestamp(7, 3) 
                        { "uid" : 218713 } -->> { "uid" : 229198 } on : shard0001 Timestamp(9, 2) 
                        { "uid" : 229198 } -->> { "uid" : 241131 } on : shard0001 Timestamp(9, 3) 
                        { "uid" : 241131 } -->> { "uid" : { "$maxKey" : 1 } } on : shard0000 Timestamp(10, 0) 
```

今度は設定が既に完了しているのでシャーディングは実行されている。


# pymongoからアクセスする

localhostからmongosにリクエストを送る

```
from pymongo import MongoClient                                                                                          
from time import sleep                                                                                                   
                                                                                                                         
#c = MongoClient(host=['db1:27011', 'db2:27011', 'db3:27011'], replicaset='rs01')                                        
#print(c.mydb.logs.count())                                                                                              
#print(c.nodes)                                                                                                          
c = MongoClient(host="core1:27000")                                                                                      
print(c.logdb.logs.count())
```

結果は次の通り

```
$ python -V
Python 3.5.1
$ pip list | grep pymongo                                                                            
pymongo (3.4.0)
$ python req.py 
150001
```

db1のmongodを落として確認してみる

```
[root@db1 mongodb]# pgrep -lf mongo
2717 ./bin/mongod -f conf/shard.conf
[root@db1 mongodb]# pkill -f mongo
```

mongosにmongoクライアントで接続して確認

```
[root@core1 mongodb]# ./bin/mongo --port 27000
MongoDB shell version: 3.2.9
connecting to: 127.0.0.1:27000/test

mongos> use logdb                                                                                                        
switched to db logdb
mongos> show collections                                                                                                 
2017-01-29T11:16:55.488+0000 E QUERY    [thread1] Error: listCollections failed: {
        "code" : 13328,
        "ok" : 0,
        "errmsg" : "connection pool: connect failed db1:27011 : couldn't connect to server db1:27011, connection attempt failed"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DB.prototype._getCollectionInfosCommand@src/mongo/shell/db.js:773:1
DB.prototype.getCollectionInfos@src/mongo/shell/db.js:785:19
DB.prototype.getCollectionNames@src/mongo/shell/db.js:796:16
shellHelper.show@src/mongo/shell/utils.js:754:9
shellHelper@src/mongo/shell/utils.js:651:15
@(shellhelp2):1:1
```

localhostからpythonでアクセス

```
$ python req.py 
Traceback (most recent call last):
  File "req.py", line 8, in <module>
    print(c.logdb.logs.count())
  File "/home/kw/.pyenv/versions/3.5.1/lib/python3.5/site-packages/pymongo/collection.py", line 1354, in count
    return self._count(cmd, collation)
  File "/home/kw/.pyenv/versions/3.5.1/lib/python3.5/site-packages/pymongo/collection.py", line 1310, in _count
    collation=collation)
  File "/home/kw/.pyenv/versions/3.5.1/lib/python3.5/site-packages/pymongo/collection.py", line 232, in _command
    collation=collation)
  File "/home/kw/.pyenv/versions/3.5.1/lib/python3.5/site-packages/pymongo/pool.py", line 419, in command
    collation=collation)
  File "/home/kw/.pyenv/versions/3.5.1/lib/python3.5/site-packages/pymongo/network.py", line 116, in command
    parse_write_concern_error=parse_write_concern_error)
  File "/home/kw/.pyenv/versions/3.5.1/lib/python3.5/site-packages/pymongo/helpers.py", line 210, in _check_command_response
    raise OperationFailure(msg % errmsg, code, response)
pymongo.errors.OperationFailure: socket exception [CONNECT_ERROR] for db1:27011
```