샤딩이란
데이터를 여러 대의 디비에 분산시켜 저장하는 기술을 말한다.
몽고디비는 샤딩을 자동으로 처리해준다.
샤딩을 ReplicaSet에 구성하기
Config 서버
샤딩에 필요한 메타데이터가 저장되며, Config 서버 수는 1 또는 3개만 가능하다.
서버 수가 불일치 하다면, "BadValue need either 1 or 3 configdbs" 오류 메시지가 출력된다.
configsvr=true를 해준다.
Config 서버 실행
$ mongod --config /etc/mongod_conf1.conf
Mongos 서버
데이터를 라우팅 시켜주는 서버이며, 여러 대를 실행 시킬 수 있다.
샤딩 데이터를 디비에 읽고 쓰기 위해서 Mongod가 아닌 Mongos 서버에 연결해야 한다.
샤당할 서버를 등록하기에 앞서 ReplicaSet 구성하기를 참고하여 first와 second군을 만들어 둔다.
configdb에 Config서버를 추가하고, chunkSize=1로 설정해 샤딩테스트를 용이하게 한다.
Mongos 서버 실행과 샤딩 정보 등록
## Mongos 서버 실행
$ mongos -f /etc/mongos.conf
## Mongos에 접속
$ mongo localhost:27001/admin
## 샤딩서버 등록
## localhost:10003과 localhost:10006은 Arbiter 이므로 추가해도 등록되지 않으니, 추가해도 되고 안해도 된다.
mongos> db.runCommand( { addShard : "first/localhost:10001,localhost:10002,localhost:10003" } )
{ "shardAdded" : "first", "ok" : 1 }
mongos> db.runCommand( { addShard : "second/localhost:10004,localhost:10005,localhost:10006" } )
{ "shardAdded" : "second", "ok" : 1 }
## 샤딩 리스트 확인
mongos> db.runCommand({listShards:1})
{
"shards" : [
{
"_id" : "first",
"host" : "first/localhost:10001,localhost:10002"
},
{
"_id" : "second",
"host" : "second/localhost:10004,localhost:10005"
}
],
"ok" : 1
}
## 샤딩할 디비 등록
mongos> db.runCommand( { enableSharding : "test" } )
{ "ok" : 1 }
## 샤드키 설정
## 이미 설정하였다면 넘어가자
mongos> use test
switched to db test
mongos> db.test_collection.ensureIndex({number:1})
{
"raw" : {
"first/localhost:10001,localhost:10002" : {
"createdCollectionAutomatically" : true,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
},
"ok" : 1
}
## 샤딩할 컬렉션과 샤드키 등록
mongos> use admin
switched to db admin
mongos> db.runCommand( { shardCollection : "test.test_collection", key : {"number":1} })
{ "collectionsharded" : "test.test_collection", "ok" : 1 }
샤딩이 잘 되는지 테스트
## Mongos 서버에 연결해야 한다.
## 10만개를 생성해 넣어보자.
mongos> use test
switched to db test
mongos> for (var i = 0; i < 100000; ++i) db.test_collection.save({number:i})
WriteResult({ "nInserted" : 1 })
## 각 서버에 어떻게 데이터가 분산되어 있는지 확인해 보자.
## 샤드키(number)값의 범위에 따라 분산되어 있다.
mongos> db.printShardingStatus()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"version" : 4,
"minCompatibleVersion" : 4,
"currentVersion" : 5,
"clusterId" : ObjectId("53a9318e6d2c219bb5966c5f")
}
shards:
{ "_id" : "first", "host" : "first/localhost:10001,localhost:10002" }
{ "_id" : "second", "host" : "second/localhost:10004,localhost:10005" }
databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "test", "partitioned" : true, "primary" : "first" }
test.test_collection
shard key: { "number" : 1 }
chunks:
first 3
second 3
{ "number" : { "$minKey" : 1 } } -->> { "number" : 0 } on : first Timestamp(4, 0)
{ "number" : 0 } -->> { "number" : 13026 } on : first Timestamp(3, 1)
{ "number" : 13026 } -->> { "number" : 38291 } on : first Timestamp(5, 0)
{ "number" : 38291 } -->> { "number" : 60483 } on : second Timestamp(5, 1)
{ "number" : 60483 } -->> { "number" : 86544 } on : second Timestamp(4, 4)
{ "number" : 86544 } -->> { "number" : { "$maxKey" : 1 } } on : second Timestamp(4, 5)
## first 서버에 연결해 몇 개가 쌓여있는지 확인
$ mongo localhost:10001/admin
MongoDB shell version: 2.6.2
connecting to: localhost:10001/admin
first:PRIMARY> use test
switched to db test
first:PRIMARY> db.test_collection.count()
38291
## number:0은 first에 있고, number:38291은 second에 분산되어 있다고 했다.
## 실제로 그런지 확인해 보자. 정상이군
first:PRIMARY> db.test_collection.find({number:0})
{ "_id" : ObjectId("53a937ecc09ddce1f1cef931"), "number" : 0 }
first:PRIMARY> db.test_collection.find({number:38291})
## second 서버에 연결해 몇 개가 쌓여있는지 확인
$ mongo localhost:10004/admin
MongoDB shell version: 2.6.2
connecting to: localhost:10004/admin
second:PRIMARY> use test
switched to db test
second:PRIMARY> db.test_collection.count()
61709
## number:0은 first에 있고, number:38291은 second에 분산되어 있다고 했다.
## 실제로 그런지 확인해 보자. 정상이군
second:PRIMARY> db.test_collection.find({number:0})
second:PRIMARY> db.test_collection.find({number:38291})
{ "_id" : ObjectId("53a93817c09ddce1f1cf8ec4"), "number" : 38291 }
테스트 결과
10만 개를 넣었을 때, 4:6비율로 분산되었고,
ReplicaSet으로 된 first 서버의 Primary서버를 강제 종료하더라도 Auto Failover가 이루어져, 문제없이 읽기와 쓰기 작업 모두 성공적으로 동작하였다.
first 서버군이 모두 종료되었을 때에는, 읽기와 쓰기작업에 요청된 샤드키값이 second 서버군에 저장되어 있거나 저장할 값이라면 오류가 없었지만, first 서버군에 저장된 데이터이거나 저장할 값이라면 오류가 발생하였다.