MongoDB를 sharding 해서 돌리면 각 shard별로 데이터를 chunk 단위로 관리하는데,
일반적으로는 알아서 잘 균등분배 해주지만 대용량을 미친 속도로 batchInsert 하거나 하다보면,
초거대 슈퍼메가 chunk가 생길 때가 있다.
그러든 아니든 chunk 단위별 사이즈를 체크하고 너무 큰 chunk는 나누는 법.
1. db.col.stats()
stats()를 해봤는데 shards 데이터를 보고, count, size가 균등분배 되었는지 확인.
만약 shards 데이터의 각 shard별로 count나 size가 균등분배 되어 있지 않고 차이가 심하다면 직접 chunk를 나눌 필요가 있다.
2. chunk size
MongoDB 명령어인 dataSize를 이용하여 각 chunk 별 사이즈 확인하기
<?PHP
$m = new MongoClient(CONNECTION_STRING);
$db = $m->DB_NAME;
// config.chunks collection에 우리가 원하는 chunk meta data가 들어 있음.
$config_chunks = $m->config->chunks;
// chunk 사이즈를 알고자 하는 collection의 name space 지정
$ns = 'DB_NAME.COLLECTION_NAME';
$q = array('ns' => $ns);
$c = $config_chunks->find($q);
foreach ($c as $v) {
// chunk별 사이즈 알아내기
$cmd = array(
'dataSize' => $ns,
'keyPattern' => SHARD_KEY,
'min' => $v['min'],
'max' => $v['max']
);
$r = $db->command($cmd);
// shard 이름
$shard = $v['shard'];
// 해당 chunk의 최소키
$min_key = json_encode($v['min']);
// 해당 chunk의 최대키
$max_key = json_encode($v['max']);
// 해당 chunk의 data size
$chunk_size = $r['size'];
// 해당 chunk에 들어있는 object 수
$chunk_count = $r['count'];
// dataSize 명령어 실행완료 시간 (millis)
$cmd_time = $r['millis'];
printf("[%s] %s ---> %s\tSIZE=%d, COUNT=%d (%.3f)\n", $shard, $min_key, $max_key, $chunk_size, $chunk_count, $cmd_time);
}
3. chunk split
위와 같은 형태의 스크립트를 실행하면 chunk들의 사이즈가 주루룩 나오는데,
잘 살펴보고 혼자만 사이즈나 object count가 많은 용납할 수 없는 chunk가 나오면 분리하자.
분리할 땐 mongos 로 접속하여 sh.splitFind() 명령어를 이용한다.
sh.splitFind(NAMESPACE, QUERY) 명령어는 NAMESPACE에서 QUERY에 해당하는 chunk를 절반으로 나눈다.
QUERY는 나누고자 하는 chunk의 min ~ max 사이에 있는 아무거나 지정될 수 있으면 된다.
// chunk size list가 있고 shard key가 id-date 형태이고 아래와 같은 chunk size 리스트가 나온다면
bloodguy_20140101 ~ cooltohate_20140201 size=1000000
cooltohate_20140201 ~ drum004_20140101 size= 500000
drum004_20140101 ~ effect1324_20140201 size= 500000
// bloodguy_20140101 ~ cooltohate_20140201 chunk가 다른 chunk들에 비해 2배의 크기이므로 절반으로 나누고자 한다.
// 해당 컬렉션에서 min ~ max 사이에 있는 아무거나 하나 가져온 다음,
db.COLLECTIION.findOne({id:{$gt:'bloodguy', $lt:'cooltohate'}})
--> {id:'bloodguyz', date:20140102, name:'백충덕'} // 뭐 이런게 하나 나왔다 치자.
// 아래처럼 명령어를 실행하면 저 chunk 는 절반으로 나뉜다.
sh.splitFind('DB_NAME.COLLECTION', {id:'bloodguyz'})
// chunk 만 나눠 놓으면 나머지는 balancer가 알아서 해준다.
// balancer가 shard간 chunk를 이동시키는 threshold는 아래와 같다.
// chunk가 20개 이하라면 shard간 chunk수가 2개 이상 차이가 날 경우 balancer 동작
// chunk가 21개에서 80개 사이라면 shard간 chunk수가 4개 이상 차이가 날 경우 balancer 동작
// chunk가 80개보다 많으면 shard간 chunk수가 8개 이상 차이가 날 경우 balancer 동작
MongoDB가 균등분배 잘해줄거라고 찰떡같이 믿고 있다가 shard 하나만 초거대 chunk를 만드는 배신을 당했다.
무조건 믿지 말고 직접 확인하자.
[참조]
dataSize: http://docs.mongodb.org/manual/reference/command/dataSize/
sh.splitFind : http://docs.mongodb.org/manual/reference/method/sh.splitFind/
sharded collection balancing : http://docs.mongodb.org/manual/core/sharding-balancing/
'DataBase' 카테고리의 다른 글
[MongoDB] MongoDB의 낙장불입. (0) | 2014.02.13 |
---|---|
[MongoDB] shard간 chunk 이동 (migrate chunks) (0) | 2014.02.13 |
[MongoDB] locks (0) | 2014.02.01 |
[MongoDB] heavy write(upsert+remove) 상황에서 고가용성을 위한 팁 (heavy write, upsert, remove, availability) (2) | 2014.01.29 |
[MongoDB] MongoDB의 제약사항들. (MongoDB limits thresholds) (0) | 2014.01.28 |