'package/mongodb'에 해당되는 글 13건
- 2011.11.01 movechunk 시에 can't find index in storeCurrentLocs 에러처리
- 2011.10.26 mongodb inline mapreduce에서 finalize에서 최종 결과 control하기
- 2011.10.19 auto balancing chunk number 변경
- 2011.07.19 MongoDB javascript engine 교체 및 튜닝
- 2011.07.01 MongoDB Sharding
- 2011.06.30 MongoDB replication
- 2011.06.30 Mongodb용 웹기반 GUI 툴 RockMongo, JmongoBrowser 설치
- 2011.06.30 mongodb shell 명령어
- 2011.06.30 mongodb driver pymongo 사용법
- 2011.06.29 Inserting
일반적으로 moveChunk 명령어에서 사용되는 find에 들어간 key에 대한 index가 없어서 생기는 문제이다
해당 key에 대해서 오름차순으로 index를 만들어줘야함
예 : db.runCommand( { moveChunk : "test.blog.posts" , find : { author : "eliot" } , to : "shard1" } )
해당 key에 대해서 오름차순으로 index를 만들어줘야함
예 : db.runCommand( { moveChunk : "test.blog.posts" , find : { author : "eliot" } , to : "shard1" } )
이경우에는 index에 ensureIndex ({'author': 1}) 있어야함
inline map/reduce의 경우 mongodb에서 하나의 object 16MB를 넘으면 안되기 때문에
최종 finalize한 결과값이 16MB안에 들어가야한다
요것을 수정해주려면 소스 코드에 박혀있는 메모리값을 수정해주던지
finalize에서 필요 없는 결과의 key값을 최종 inline map/reduce결과에서 제거해주면 해결될수도있다 (이부분은 mongodb의 용도에 따라 다르겠지만
내 용도에 한해서는 finalize에서 필요없는 key값 자체를 제거하므로 해결이 가능하다)
기본환경은 shard환경에서의 mongodb이다
finalize script에서 return null; 이거나 return을 안한 결과에 대해서는 해당 key값을 inline map/reduce 최종 값에서 제거해버리도록 코드를 수정해보자
(현재 mongodb jira에 등록은 되어있지만 2.1 버전정도에서 해결해준다고 하는데 크게 의지는 없는듯)
single server 환경에서의 inline map/reduce 수정
sharded 환경에서 inline map/reduce 수정
/db/commands/mr.cpp
최종 finalize한 결과값이 16MB안에 들어가야한다
요것을 수정해주려면 소스 코드에 박혀있는 메모리값을 수정해주던지
finalize에서 필요 없는 결과의 key값을 최종 inline map/reduce결과에서 제거해주면 해결될수도있다 (이부분은 mongodb의 용도에 따라 다르겠지만
내 용도에 한해서는 finalize에서 필요없는 key값 자체를 제거하므로 해결이 가능하다)
기본환경은 shard환경에서의 mongodb이다
finalize script에서 return null; 이거나 return을 안한 결과에 대해서는 해당 key값을 inline map/reduce 최종 값에서 제거해버리도록 코드를 수정해보자
(현재 mongodb jira에 등록은 되어있지만 2.1 버전정도에서 해결해준다고 하는데 크게 의지는 없는듯)
single server 환경에서의 inline map/reduce 수정
/db/commands/mr.cpp
/** * Applies last reduce and finalize. * After calling this method, the temp collection will be completed. * If inline, the results will be in the in memory map */ void State::finalReduce( CurOp * op , ProgressMeterHolder& pm ) { // 변경전 if ( ! _onDisk ) { // all data has already been reduced, just finalize if ( _config.finalizer ) { long size = 0; for ( InMemory::iterator i=_temp->begin(); i!=_temp->end();i++) { BSONObj key = i->first; BSONList& all = i->second; assert( all.size() == 1 ); BSONObj res = _config.finalizer->finalize( all[0] ); all.clear(); all.push_back( res ); size += res.objsize(); } _size = size; } return; } // 변경후 if ( ! _onDisk ) { // all data has already been reduced, just finalize if ( _config.finalizer ) { long size = 0; for ( InMemory::iterator i=_temp->begin(); i!=_temp->end();) { BSONObj key = i->first; BSONList& all = i->second; assert( all.size() == 1 ); BSONObj res = _config.finalizer->finalize( all[0] ); // finalize가 null을 반환하면 해당 key값은 삭제한다 if (res["value"].isNull()) { _temp->erase(i++); } else { all.clear(); all.push_back( res ); size += res.objsize(); i++; } } _size = size; } return; }
sharded 환경에서 inline map/reduce 수정
/db/commands/mr.cpp
class MapReduceFinishCommand : public Command { while ( cursor.more() || !values.empty() ) { BSONObj t; if (cursor.more()) { t = cursor.next().getOwned(); if ( values.size() == 0 ) { values.push_back( t ); continue; } if ( t.woSortOrder( *(values.begin()) , sortKey ) == 0 ) { values.push_back( t ); continue; } } BSONObj res = config.reducer->finalReduce( values , config.finalizer.get()); // finalize가 null을 반환하면 해당 key값은 삭제한다 (변경후) if (!res["value"].isNull()) { if (state.isOnDisk()) state.insertToInc(res); else state.emit(res); } values.clear(); if (!t.isEmpty()) values.push_back( t ); /* 변경전 if (state.isOnDisk()) state.insertToInc(res); else state.emit(res); values.clear(); if (!t.isEmpty()) values.push_back( t ); */ }
mongodb 사이트에서 src파일을 받은후에
s/balancer_policy.cpp 에서 balance function의 const int threshold = balancedLastTime ? 2 : 8; 부분을 수정해준다
앞부분이 (2) 각 shard간의 허용 imbalance 정도이고 (이 수치까지 balance를 맞춘후에 stop)
뒷부분이 (8) 각 shard간의 min, max chunk number 가 8이상 차이날 경우 auto balancing을 실시한다는것
파일을 수정후에
scons all 로 컴파일해주자
컴파일시 boost등의 문제가 생기면 v8 engine으로 컴파일하기쪽에서 필요한 라이브러리들을 설치하자~
s/balancer_policy.cpp 에서 balance function의 const int threshold = balancedLastTime ? 2 : 8; 부분을 수정해준다
앞부분이 (2) 각 shard간의 허용 imbalance 정도이고 (이 수치까지 balance를 맞춘후에 stop)
뒷부분이 (8) 각 shard간의 min, max chunk number 가 8이상 차이날 경우 auto balancing을 실시한다는것
파일을 수정후에
scons all 로 컴파일해주자
컴파일시 boost등의 문제가 생기면 v8 engine으로 컴파일하기쪽에서 필요한 라이브러리들을 설치하자~
메뉴얼 : http://www.mongodb.org/display/DOCS/Building
실행 환경 : ubuntu 11.04
v8 설치하기
만약에 몽고디비 src가 ~/workspace/mongodb-src-r1.8.2 에 있을경우
v8은 ~/workspace/v8 으로 받아놓자
v8 컴파일
v8 컴파일
필수 패키지 설치
sudo apt-get install subversion git-core tcsh git-core scons g++ libpcre++-dev
sudo apt-get install libboost-dev libreadline-dev xulrunner-1.9.1-dev
v8 다운로드
svn checkout http://v8.googlecode.com/svn/trunk/ v8
ubuntu 64bit에서 컴파일하기 위해서
scons arch=x64
mongodb 소스파일받기
1. http://www.mongodb.org/downloads 에서 가장 오른쪽의 source부분
2. wget http://downloads.mongodb.org/src/mongodb-src-r1.8.2.tar.gz
mongodb 컴파일하기
필수 패키지 설치
필수 패키지 설치
apt-get -y install tcsh git-core scons g++
apt-get -y install libpcre++-dev libboost-dev libreadline-dev xulrunner-1.9.2-dev
apt-get -y install libboost-program-options-dev libboost-thread-dev libboost-filesystem-dev libboost-date-time-dev
scons all --usev8
v8으로 계속 m/r을 돌리다보면 메모리릭이 있는거 같다..... jira에 해당 버그가 reporting되어 있는거 같은데....나중에 고친다고함 ㅋ
v8으로 계속 m/r을 돌리다보면 메모리릭이 있는거 같다..... jira에 해당 버그가 reporting되어 있는거 같은데....나중에 고친다고함 ㅋ
- 특징
- 부하와 분산에 따라서 자동의로 균형을 맞춰준다
- 새머신의 추가히기 쉽다
- 자동 복구가 가능하다
- 수천개의 노드도 수평적으로 확장가능
- config server, mongos, mongod 로 구성됨
- 부하와 분산에 따라서 자동의로 균형을 맞춰준다
- 한계
- sharding내에서의 인증과 보안문제
- sharding
키가되는 필드로 각 머신의로 나뉘어서 들어간다
해당키에 대해서 각 머신은 chunk라는 단위로 데이터를 쌓는다
user는 mongos 를 통해서 자신의 요청에 적합한 shard로 명령을 내린다
sharding은 collection단위로 실행된다
- balancing
하나의 shard node가 너무 많이 차게 되면 분산된다
- failover
- scailing model
auto sharding model은 구글의 big table, yahoo위 pnuts 와 유사하다
order-preserving partitioning이 사용되어짐
- shard keys
index처럼 여러개를 key로 갖을수 있고 order-preserving partitioning이 사용되므로 각 shard에는
어느정도 range의 데이터드이 뭉쳐서 들어가게 된다
해당 range는 mongo config서버에 저장된다
- chunks
chunk는 collection, maxkey, minkey 이렇게 3개로 나타진다
보통 64M 까지 증가한다. 해당 용량을 넘어서면 2개의 chunk로 나누어진다
키를 선택할때는 해당 키가 균등하게 데이터를 분산할수 있게할수 있는 값인지 판단필요
만약의 single key를 사용할때 해당 key에 대해서 끝도 없이 커질 위험이 있을 경우에는 여러개의 key를 shard key로 사용해야함
- config server
shard server의 정보와 chunk정보를 갖고있다
chunk데이터가 config server 의 main data이다
config server끼리는 모든 chunk데이터의 복사본을 갖는다
chunk데이터는 consistency를 유지하기 위해서 2phase commit 이 발생한다
config server는 자신만의 replica set 구조를 갖는다 (일반적인 mongodb의 replica set이랑 다름)
config server가 하나라도 죽으면 다른 config server는 read만할수 있다 (이때 mongo cluster에도 read, write가능하다)
- routing process (mongos)
mongo cluster를 단일 system처럼 생각할 수 있게 routing역할을한다
user로부터 request가 오면 적합한 server로 request를 보내거나 취합해서 user에게 돌려준다
mongos는 독자적인 영구적이 저장이 없고 startup될때 config server로부터 데이터를 받고 데이터가 변경되면
config server로부터 해당 변경 데이터를 받는다
- opereation종류
global : 전체 shard로 부터 연산 필요
target : single 또는 몇개의 shard로부터 연산
- sharding 만들기
물리적 서버 2대를 기준으로 만든다고생각 (server1, server2로 구성)
shard는 2개로 구성예정 각각의 replication을 server1,2에 분산해서 처리
1. start mongod
먼저 필요한 디렉토리 생성
server1 : mkdir -p /home/yoga/workspace/mall/shard1/log /home/yoga/workspace/mall/shard1/data /home/yoga/workspace/mall/shard2/log /home/yoga/workspace/mall/shard2/data
server2 : mkdir -p /home/yoga/workspace/mall/shard1/log /home/yoga/workspace/mall/shard1/data /home/yoga/workspace/mall/shard2/log /home/yoga/workspace/mall/shard2/data
shard1 구성 (replica set 구성)
server1에서 : mongod --shardsvr --replSet shard1 --fork --logpath /home/yoga/workspace/mall/shard1/log/mongodb.log --logappend --dbpath /home/yoga/workspace/mall/shard1/data --rest --oplogSize 2048 --port 30000
server2에서 : mongod --shardsvr --replSet shard1 --fork --logpath /home/yoga/workspace/mall/shard1/log/mongodb.log --logappend --dbpath /home/yoga/workspace/mall/shard1/data --rest --oplogSize 2048 --port 30000
shard2 구성 (replica set 구성)
server1에서 : mongod --shardsvr --replSet shard2 --fork --logpath /home/yoga/workspace/mall/shard2/log/mongodb.log --logappend --dbpath /home/yoga/workspace/mall/shard2/data --rest --oplogSize 2048 --port 30001
server2에서 : mongod --shardsvr --replSet shard2 --fork --logpath /home/yoga/workspace/mall/shard2/log/mongodb.log --logappend --dbpath /home/yoga/workspace/mall/shard2/data --rest --oplogSize 2048 --port 30001
replica set config 구성 : server1에서는 shard1이 master, server2에서는 shard2가 master
server1 또는 2 아무곳에서나
mongo --port 30000
config = { _id : "shard1", members : [
{_id: 0, host: "server1의ip:30000" , priority : 1},
{_id: 1, host: "server2의ip:30000", priority: 1}]}
rs.initiate(config);
exit
mongo --port 30001
config = { _id : "shard2", members : [
{_id: 0, host: "server1의ip:30001" , priority : 1},
{_id: 1, host: "server2의ip:30001", priority: 1}]}
rs.initiate(config);
exit
server1에서는 shard1이 master로 server2에서는 shard2가 master로 될수 있게 셋팅하자
mongo shell을 통해서 master가 잘못 잡혔으면 해당 서버에서 rs.stepDown()을 해주자
(처음에 지정할 마스터를 선택하는게 있을듯.....문서좀 뒤져봐야겠다)
2. config server
config server를 위한 디렉토리 설정 (server1, 2에서 실행, 1 or 3개 띄어야해서 2번서버에 42000port로 하나더 띄움)
mkdir -p /home/yoga/workspace/mall/config/log /home/yoga/workspace/mall/config/data
server1,2에서 : mongod --configsvr --fork --port 40000 --logpath /home/yoga/workspace/mall/config/log/mongodb.log --logappend --dbpath /home/yoga/workspace/mall/config/data --rest
server2에만(디렉토리도 만들어주자 log3, data3으로) : mongod --configsvr --fork --port 42000 --logpath /home/yoga/workspace/mall/config/log3/mongodb.log --logappend --dbpath /home/yoga/workspace/mall/config/data3 --rest
3. mongos 셋팅
server1,2에 셋팅
mkdir -p /home/yoga/workspace/mall/router/log /home/yoga/workspace/mall/router/data
server1, 2에서 : mongos --port 50000 --configdb server1:40000,server2:40000,server2:42000 --logpath /home/yoga/workspace/mall/router/log/mongodb.log --logappend --fork
mongos에 shard정보를 입력하기 (하나만하면 다른 모든 mongos에 전파되는듯..)
mongo server1:50000/admin
db.runCommand({addshard:"shard1/server1:30000,server2:30000"})
db.runCommand({addshard:"shard2/server1:30001,server2:30001"})
db.runCommand({listshards:1}) : 현재 셋팅된 shard 알려줌
db.runCommand({enablesharding: "mall"}) : shard할 데이터베이스 이름 (요걸안하면 첫번째 shard에 계속 저장된다)
db.runCommand({ shardcollection: "mall.product", key : {p_id:1, p_name:1}}) : shard할 collection 셋팅 및 shard key지정
2가지의 replication을 지원
ReplicaSet 구성 (single server로 구성시)
http://www.mongodb.org/display/DOCS/Replica+Set+Tutorial
mongod --fork --logpath /home/yoga/workspace/mongod1/log/mongodb.log --logappend --dbpath / home/yoga/workspace/mongod1/data --rest --replSet mall --port 27018 --oplogSize 2048
mongod --fork --logpath /home/yoga/workspace/mongod2/log/mongodb.log --logappend --dbpath / home/yoga/workspace/mongod2/data --rest --replSet mall --port 27019 --oplogSize 2048
mongod --fork --logpath /home/yoga/workspace/mongod3/log/mongodb.log --logappend --dbpath / home/yoga/workspace/mongod3/data --rest --replSet mall --port 27020 --oplogSize 2048
mongo --port 27018
config = {
_id: 'foo',
members: [ {_id: 0, host: 'localhost:27017'},
{_id: 1, host: 'localhost:27018'},
{_id: 2, host: 'localhost:27019'}] }
rs.initiate(config);
음 master에 엄청난 양의 local데이터가 쌓이는데.... oplog파일 사이즈를 42기가로 잡아서 그런거 같은데...이걸 처음에 셋팅해줘야할듯.
oplog 처음에 잡는 사이즈가 전체 디스크의 5%를 잡는다고한다..... 시작할때 --oplogSize 2048 같이 명시적으로 주도록하자
replicaSet중 하나를 arbiter로 만들기위해서는config에 arbiterOnly: True를 추가해서 rs.reconfig(config) 를 실행해주면됨
mongo shell에서 slave에서 read하기 위해서는 rs.slaveOk() 를 slave에서 실행후에 find해보면된다
driver에서는 slaveok=True옵션을 사용
replicaSet에 관한 명령어 설명 : http://www.mongodb.org/display/DOCS/Replica+Set+Commands
slave가 oplog로 복구 못할정도가 될경우 해결 방법
1. master에서 lock을 걸고 fsync를 통해서 파일에 동기화시킨후 copy
2. 해당 slave에 data 디렉토리안에 데이터를 전부 삭제하고 재투입 (자동복구...시간 오래걸림)
- master-slave
master 1대에 slave여러개
- replica-set ( version >= v1.6)
automatic fail-over and recovery
using sharding
현재 master가 없다면 자체적으로 master를 선정한다
master가 변경되면 driver들은 자체적으로 변경된 master로 write를 보낸다
read data를 분산시킨다
ReplicaSet 구성 (single server로 구성시)
http://www.mongodb.org/display/DOCS/Replica+Set+Tutorial
mongod --fork --logpath /home/yoga/workspace/mongod1/log/mongodb.log --logappend --dbpath / home/yoga/workspace/mongod1/data --rest --replSet mall --port 27018 --oplogSize 2048
mongod --fork --logpath /home/yoga/workspace/mongod2/log/mongodb.log --logappend --dbpath / home/yoga/workspace/mongod2/data --rest --replSet mall --port 27019 --oplogSize 2048
mongod --fork --logpath /home/yoga/workspace/mongod3/log/mongodb.log --logappend --dbpath / home/yoga/workspace/mongod3/data --rest --replSet mall --port 27020 --oplogSize 2048
mongo --port 27018
config = {
_id: 'foo',
members: [ {_id: 0, host: 'localhost:27017'},
{_id: 1, host: 'localhost:27018'},
{_id: 2, host: 'localhost:27019'}] }
rs.initiate(config);
음 master에 엄청난 양의 local데이터가 쌓이는데.... oplog파일 사이즈를 42기가로 잡아서 그런거 같은데...이걸 처음에 셋팅해줘야할듯.
oplog 처음에 잡는 사이즈가 전체 디스크의 5%를 잡는다고한다..... 시작할때 --oplogSize 2048 같이 명시적으로 주도록하자
replicaSet중 하나를 arbiter로 만들기위해서는config에 arbiterOnly: True를 추가해서 rs.reconfig(config) 를 실행해주면됨
mongo shell에서 slave에서 read하기 위해서는 rs.slaveOk() 를 slave에서 실행후에 find해보면된다
driver에서는 slaveok=True옵션을 사용
replicaSet에 관한 명령어 설명 : http://www.mongodb.org/display/DOCS/Replica+Set+Commands
slave가 oplog로 복구 못할정도가 될경우 해결 방법
1. master에서 lock을 걸고 fsync를 통해서 파일에 동기화시킨후 copy
2. 해당 slave에 data 디렉토리안에 데이터를 전부 삭제하고 재투입 (자동복구...시간 오래걸림)
JMongoBrowser 설치
추가로 설치할것이 없고 java만 설치되어있으면된다
http://www.antoinegirbal.com/jmongobrowser/
받아서 그냥 설치하면되고 file->connection->servers에서 ip:port만 넣고 그냥 선택하면된다
RockMongo 설치
oracle client같은 기능을 갖는 GUI 툴을 찾다보니 php기반의 rockmongo를 찾았다
이것 말고도 phpmyadmin이라는 것도 있는듯.
설치에 필요한것 apache, php, mongodb php driver, rockmongo
apache, php는 ubuntu에 설치되어 있는 것으로 사용
http://code.google.com/p/rock-php/downloads/list
최신버전을 다운로드 압축을 /var/www/rock_mongo 에 푼다 (/var/www는 자신의 취향에 따라 선택. 후에 apache config에서도
이 디렉토리에 맞게 수정이 필요함)
rock_mongo 디렉토리 바로 하위에 php파일등이 오게 될것임
php용 mongodb driver 설치
http://www.mongodb.org/display/DOCS/PHP+Language+Center
apache 셋팅
httpd.conf파일에 alias 걸어주기
RockMongo 동작확인
http://host_ip/rock_mongo/index.php
처음 동작시 계정은 admin/admin
메인화면에서 login없애기 위해서
추가로 설치할것이 없고 java만 설치되어있으면된다
http://www.antoinegirbal.com/jmongobrowser/
받아서 그냥 설치하면되고 file->connection->servers에서 ip:port만 넣고 그냥 선택하면된다
RockMongo 설치
oracle client같은 기능을 갖는 GUI 툴을 찾다보니 php기반의 rockmongo를 찾았다
이것 말고도 phpmyadmin이라는 것도 있는듯.
설치에 필요한것 apache, php, mongodb php driver, rockmongo
apache, php는 ubuntu에 설치되어 있는 것으로 사용
http://code.google.com/p/rock-php/downloads/list
최신버전을 다운로드 압축을 /var/www/rock_mongo 에 푼다 (/var/www는 자신의 취향에 따라 선택. 후에 apache config에서도
이 디렉토리에 맞게 수정이 필요함)
rock_mongo 디렉토리 바로 하위에 php파일등이 오게 될것임
php용 mongodb driver 설치
http://www.mongodb.org/display/DOCS/PHP+Language+Center
sudo pecl install mongo vi /etc/php5/apache2/php.ini // Dynamic Extensions쪽에 extension=mongo.so 추가후 /etc/init.d/apache2 restart
apache 셋팅
httpd.conf파일에 alias 걸어주기
Alias /rock_mongo /var/www/rock_mongo /etc/init.d/apache2 restart
RockMongo 동작확인
http://host_ip/rock_mongo/index.php
처음 동작시 계정은 admin/admin
메인화면에서 login없애기 위해서
// config.php파일에서 요걸 수정 $MONGO["servers"][$i]["control_auth"] = false;
각각의 위치에서 help를 치면 현재 위치에서 입력가능한 명령어 목록이 나옴
use database이름 // database이름으로 namespace를 변경
db.dropDatabase() // 현재 namespace의 database를 삭제
db.collection명.drop() // 현재 namespace의 database안에 있는 collection명을 삭제
db.collection명.save(xx) // 현재 namespace의 database안에 있는 collection명에 xx데이터 insert
// index추가하기
db.collection명.ensureIndex({field명:1}) // value는 1(ascending) or -1 (descending)
db.collection명.ensureIndex({field명:1}, {background:treu}) // background index (일반적인 ensureIndex는 다른 op를 block시키는데 이건아님)
http://www.mongodb.org/display/DOCS/Drivers 에 최신 python driver에 대한 정보가 있다.
install은 해당 홈페이지에 보면 자세히 나와있다
easy_install pymongo # to install
easy_install -U pymongo # to upgrade
1. indexing관련
indexing을 많이 할 수록 write가 느려지지만 read는 빨라 질 수 있다.
2. collection 갯수과 관련
mongodb는 collection data를 countinuous하게 disk에 쓰기때문에 하나의 collectoin에 모든 데이터를 넣었을 경우에는
성능상의 이슈가 생길 수 있다
indexing을 많이 할 수록 write가 느려지지만 read는 빨라 질 수 있다.
2. collection 갯수과 관련
mongodb는 collection data를 countinuous하게 disk에 쓰기때문에 하나의 collectoin에 모든 데이터를 넣었을 경우에는
성능상의 이슈가 생길 수 있다