http://mobicon.tistory.com/142
MongoDB의 Replica Set을 만들어 보자. 먼저 Master/Slave와 Primary/Secondary 순으로 본다. Master/Slave는 Slave에서 Read가 된다. 그러나 Primary/Secondary에서 Secondary는 Read도 되지 않는다.
1. Replica Set 만들기 위한 Master / Slave 에 대해 알아보자. (Replica Set은 아니다)
- Master로 DB 수행하기 : master의 mongo에서 CRUD 가능
$ ./mongod -dbpath /home/dowon/MongoDB/db01 --master &
만일 db가 비정상 종료되었다면
$ ./mongod -dbpath /home/dowon/MongoDB/db01 --master --repair &
수행후에 다시 $ ./mongod -dbpath /home/dowon/MongoDB/db01 --master & 를 수행한다.
... 하기 메세지 나오면 정상 부팅
Fri Jan 4 19:29:59 [initandlisten] Unable to check for journal files due to: boost::filesystem::basic_directory_iterator constructor: No such file or directory: "/home/dowon/MongoDB/db01/journal"
Fri Jan 4 19:29:59 [initandlisten] waiting for connections on port 27017
Fri Jan 4 19:29:59 [websvr] admin web console waiting for connections on port 28017
- Slave로 DB 수행하기 : -slave 옵션
+ slave의 mongo에서 CUD 안됨. Read만 가능하다.
+ source 지정하여 replica set 만들 master가 누구인지 알려준다.
+ 기존에 single로 사용하던 mongod를 master/slave로 묶고자 할 경우 기존 데이터를 slave로 복제하기 잘 안됨
-> 다른 디렉토리로 복사해서 그런가? 테스트 필요함
+ 신규로 master/slave를 띄워서 save 또는 insert 하였을 때 slave 쪽 디렉토리에 db 파일이 제대로 복제됨
$ ./mongod --dbpath /home/dowon/MongoDB/db02 --port 27018 --slave --source localhost:27017 &
...
Fri Jan 4 19:12:46 [initandlisten] Unable to check for journal files due to: boost::filesystem::basic_directory_iterator constructor: No such file or directory: "/home/dowon/MongoDB/db02/journal"
Fri Jan 4 19:12:46 [initandlisten] waiting for connections on port 27018 <-- 정상 부팅
Fri Jan 4 19:12:46 [websvr] admin web console waiting for connections on port 28018
// 하기 메세지는 master에 있는 데이터 파일을 slave로 복사해 온다. 마치 git의 pull과 유사한 느낌 ^^
Fri Jan 4 19:12:47 [FileAllocator] done allocating datafile /home/dowon/MongoDB/db02/local.ns, size: 16MB, took 0.001 secs
Fri Jan 4 19:12:48 [FileAllocator] allocating new datafile /home/dowon/MongoDB/db02/local.0, filling with zeroes...
Fri Jan 4 19:12:48 [replslave] build index done. scanned 0 total records. 0 secs
// db02 디렉토리에 가보면 db01에 있던 데이터베이스 mydb가 copy되어 있는 것을 볼 수 있다.
Fri Jan 4 19:12:48 [replslave] resync: dropping database mydb
Fri Jan 4 19:12:48 [replslave] resync: cloning database mydb to get an initial copy
Fri Jan 4 19:12:48 [FileAllocator] allocating new datafile /home/dowon/MongoDB/db02/mydb.ns, filling with zeroes...
Fri Jan 4 19:12:48 [FileAllocator] done allocating datafile /home/dowon/MongoDB/db02/mydb.ns, size: 16MB, took 0.045 secs
Fri Jan 4 19:12:49 [replslave] resync: done with initial clone for db: mydb
Fri Jan 4 19:12:49 [FileAllocator] done allocating datafile /home/dowon/MongoDB/db02/mydb.1, size: 32MB, took 0.085 secs
2. Replica Set default 만들기
- replica set 구동하기 : db11, db12, db13 3개를 띄운다. replica set 명칭은 dowon01 이다.
- 디렉토리를 3개 만들고 각 디렉토리별로 서로 다른 port로 replica set 1개를 만들어 본다.
- mongod를 shutdown 시키고 싶을 경우 : mongo 쉘에서 db.shutdownServer({timeoutSecs: 60}); - 메뉴얼
- 결론 : mongod를 여러개 띄워서 파일시스템의 약점을 극복한다 (High Availability - HA 구성)
//////////////////////////////////////
// Replica Set 을 1개 만든다
$ ./mongod --replSet dowon01 --port 30000 --dbpath /home/dowon/MongoDB/db11
$ ./mongod --replSet dowon01 --port 40000 --dbpath /home/dowon/MongoDB/db12
$ ./mongod --replSet dowon01 --port 50000 --dbpath /home/dowon/MongoDB/db13
// 하기 환경설정관련 에러가 나온다 (정상 - 아직 환경설정 안했기 때문에 ^^)
... 중략 ...
Fri Jan 25 23:14:06 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Fri Jan 25 23:14:23 [initandlisten] connection accepted from 127.0.0.1:34440 #1 (1 connection now open)
Fri Jan 25 23:14:26 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
/////////////////////////////////////
// mongo client 접속 하기
[dowon@localhost mongodb]$ ./mongo localhost:30000
MongoDB shell version: 2.2.2
connecting to: localhost:30000/test
> show dbs
local (empty)
> exit
bye
[dowon@localhost mongodb]$ ./mongo localhost:40000
MongoDB shell version: 2.2.2
connecting to: localhost:40000/test
> show dbs
local (empty)
> exit
bye
[dowon@localhost mongodb]$ ./mongo localhost:50000
MongoDB shell version: 2.2.2
connecting to: localhost:50000/test
> show dbs
local (empty)
- Configuration 작업하기
///////////////////////////////////////////////////
// PRIMARY + SECONDARY Replica Set 만들기
[dowon@localhost mongodb]$ ./mongo localhost:30000
MongoDB shell version: 2.2.2
connecting to: localhost:30000/test
> var config={_id:'dowon01', members:[{_id:0, host:30000},
... {_id:1, host:40000}^C
// 환경 객체를 만든다
> var config={_id:'dowon01', members:[
{_id:0, host:'localhost:30000'},
{_id:1, host:'localhost:40000'},
{_id:2, host:'localhost:50000'}]
}
// replica set을 초기화 한다.
> rs.initiate(config);
{
"info" : "Config now saved locally. Should come online in about a minute.",
"ok" : 1
}
// 3000 port의 메세지를 보면 다음과 같다.
// 1) config 없을 때 나오는 메세지이다.
Fri Jan 4 21:20:29 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Fri Jan 4 21:20:39 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
// 2) rs.initiate를 수행하면 하기와 같은 메세지가 나온다.
Fri Jan 4 21:20:44 [conn2] replSet replSetInitiate admin command received from client
Fri Jan 4 21:20:44 [conn2] replSet replSetInitiate config object parses ok, 3 members specified
Fri Jan 4 21:20:44 [conn2] replSet replSetInitiate all members seem up
Fri Jan 4 21:20:44 [conn2] ******
Fri Jan 4 21:20:44 [conn2] replSet info saving a newer config version to local.system.replset
Fri Jan 4 21:20:44 [conn2] replSet saveConfigLocally done
Fri Jan 4 21:20:44 [conn2] replSet replSetInitiate config now saved locally. Should come online in about a minute.
Fri Jan 4 21:20:44 [conn2] command admin.$cmd command: { replSetInitiate: { _id: "dowon01", members: [ { _id: 0.0, host: "localhost:30000" }, { _id: 1.0, host: "localhost:40000" }, { _id: 2.0, host: "localhost:50000" } ] } } ntoreturn:1 keyUpdates:0 locks(micros) W:431969 reslen:112 477ms
Fri Jan 4 21:20:49 [rsStart] replSet I am localhost:30000
Fri Jan 4 21:20:49 [rsStart] replSet STARTUP2
Fri Jan 4 21:20:49 [rsHealthPoll] replSet member localhost:40000 is up
Fri Jan 4 21:20:49 [rsHealthPoll] replSet member localhost:50000 is up
Fri Jan 4 21:20:50 [initandlisten] connection accepted from 127.0.0.1:43880 #3 (2 connections now open)
Fri Jan 4 21:20:50 [rsSync] replSet SECONDARY
... 중략 ...
> <== enter key를 치면 하기와 같은 프롬프트로 자동 변경된다
dowon01:PRIMARY> <== "replicaSet명칭:PRIMARY>" 명칭이 나온다
////////////////////////////////////////////
// 40000, 50000 번의 client를 들어가 보자
[dowon@localhost mongodb]$ ./mongo localhost:40000
MongoDB shell version: 2.2.2
connecting to: localhost:40000/test
dowon01:SECONDARY>
[dowon@localhost mongodb]$ ./mongo localhost:50000
MongoDB shell version: 2.2.2
connecting to: localhost:50000/test
dowon01:SECONDARY>
//////////////////////////////////////////
// SECONDARY 에서 하기와같은 에러 발생시 rs.slaveOk() 수행
[mongodb@localhost ~]$ ./mongo localhost:40000
MongoDB shell version: 2.2.2
connecting to: localhost:20000/test
dowon01:SECONDARY> show dbs
dowonDB 0.0625GB
local 0.125GB
test (empty)
dowon01:SECONDARY> use dowonDB
switched to db dowonDB
dowon01:SECONDARY> db
dowonDB
dowon01:SECONDARY> show collections
Fri Jan 25 23:45:06 uncaught exception: error: { "$err" : "not master and slaveOk=false", "code" : 13435 }
// primary 의 데이터를 가져온다
dowon01:SECONDARY> rs.slaveOk()
dowon01:SECONDARY> show collections
test
system.indexes
//////////////////////////////////////////
// PRIMARY 에서 데이터베이스 생성하기
dowon01:PRIMARY> db
test
dowon01:PRIMARY> use peopleDB
switched to db peopleDB
dowon01:PRIMARY> db.people.insert({_id:1, age:11, name:'dowon1', sex:false});
dowon01:PRIMARY> db.people.insert({_id:2, age:22, name:'dowon2', sex:true});
dowon01:PRIMARY> db.people.insert({_id:3, age:33, name:'dowon3', sex:false});
dowon01:PRIMARY> db.people.find();
{ "_id" : 1, "age" : 11, "name" : "dowon1", "sex" : false }
{ "_id" : 2, "age" : 22, "name" : "dowon2", "sex" : true }
{ "_id" : 3, "age" : 33, "name" : "dowon3", "sex" : false }
////////////////////////////////////////////////////////////////////////
// SECONDARY에서 데이터베이스를 READ해 보면 에러가 발생한다
// Replica Set의 Secondary는 Slave가 아니기 때문에 사용할 수 없다.
// 즉, Primary가 down 되어야 사용 가능하다.
// 단, 1)의 Master/Slave 구조에서 Slave는 READ가 가능하다.
[dowon@localhost mongodb]$ ./mongo localhost:50000
MongoDB shell version: 2.2.2
connecting to: localhost:50000/test
dowon01:SECONDARY> show dbs // 데이터베이스 보기
local 0.125GB
peopleDB 0.0625GB
dowon01:SECONDARY> use peopleDB // 해당 데이터베이스로 switching하여 사용하기
switched to db peopleDB
dowon01:SECONDARY> show collections // 해당 데이터베이스의 테이블(?) 보기
Fri Jan 4 21:31:59 uncaught exception: error: { "$err" : "not master and slaveOk=false", "code" : 13435 }
dowon01:SECONDARY> db
peopleDB
dowon01:SECONDARY> db.people.find(); // "db"는 peopleDB를 가르키는 포인터
error: { "$err" : "not master and slaveOk=false", "code" : 13435 }
위 명령의 구조는 다음과 같다. (참조 19page)
- Primary를 종료하면 Sencodary가 Primary로 자동 변경된다
[dowon@localhost mongodb]$ ./mongo localhost:40000
MongoDB shell version: 2.2.2
connecting to: localhost:40000/test
... 중략
dowon01:SECONDARY> show collections
Fri Jan 4 21:31:33 uncaught exception: error: { "$err" : "not master and slaveOk=false", "code" : 13435 }
dowon01:SECONDARY>
// 30000 port mongoDB를 down시키고 4000 port의 mongo client에서 enter를 치면 하기와 같이 primary로 바뀐다.
dowon01:PRIMARY>
// Primary 이므로 CRUD가 가능해 진다.
dowon01:PRIMARY> show collections
people
system.indexes
dowon01:PRIMARY> db.people.insert({_id:4, age:44, name:'youngsik', sex:true});
dowon01:PRIMARY> db.people.find();
{ "_id" : 1, "age" : 11, "name" : "dowon1", "sex" : false }
{ "_id" : 2, "age" : 22, "name" : "dowon2", "sex" : true }
{ "_id" : 3, "age" : 33, "name" : "dowon3", "sex" : false }
{ "_id" : 4, "age" : 44, "name" : "youngsik", "sex" : true }
/////////////////////////////////////////////////////////////////////
// 다시 30000 port를 기동시키고, 3000 port client로 접속한다.
// 40000 port가 그대로 Primary로 존재하고, 30000 port는 Secondary로 된다.
i Jan 4 21:42:46 trying reconnect to localhost:30000
Fri Jan 4 21:42:46 reconnect localhost:30000 ok
dowon01:SECONDARY>
3) Replca Set 기본과 Master/Slave를 결합한 형태
* 참조 20page
< 참조 >
- High Availabiltity & Replica Sets with mongoDB
http://www.slideshare.net/shaolintiger/high-availabiltity-replica-sets-with-mongodb
- Sharding by mongodb/10gen on Nov 28, 2012
http://www.slideshare.net/mongodb/sharding-15392976
- Sharding morning session
http://www.slideshare.net/mongodb/sharding-morning-session
- Sharding - Seoul 2012
http://www.slideshare.net/mongodb/sharding-seoul-2012-15576057
- Replication and Replica Sets
http://www.slideshare.net/mongodb/replication-and-replica-sets-tokyo-2012
- MongoDB Basic Concepts
http://www.slideshare.net/mongodb/mongodb-basic-concepts-15674838
- A Morning with MongoDB - Helsinki
http://www.slideshare.net/mongodb/morning-with-mongo-db-helsinki-1
- MongoDB Roadmap
http://www.slideshare.net/mongodb/next-15674517