mongod --replSet tt --config=/etc/mongodb.conf <-- 이걸로 하세요 ~
echo "deb http://repo.mongodb.org/apt/ubuntu "$(lsb_release -sc)"/mongodb-org/3.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.0.list
apt-get update
apt-get install mongodb-org=3.0.2 mongodb-org-server=3.0.2 mongodb-org-shell=3.0.2 mongodb-org-mongos=3.0.2 mongodb-org-tools=3.0.2
_id : "pp_mongo",
members : [
{_id : 0, host : "192.168.0.12:27017"},
{_id : 1, host : "192.168.0.13:27017"},
{_id : 2, host : "192.168.0.14:27017", arbiterOnly: true},
]
}
rs.initiate(config);
최소한의 디비 구성
1개의 Primary DB + 1개의 Secondary DB + 1개의 Arbiter DB(Secondary DB)로 구성한다.
Primary DB
원본 데이터가 저장되는 디비이며 Read & Write 요청을 처리한다.
Secondary DB
원본 데이터의 사본을 저장하는 디비이며, Read 요청을 처리한다.
장애가 발생하면, 투표를 하여 Secondary DB 중 하나를 선택하여 Primary DB로 승격시킨다.
Arbiter DB
장애 발생시 투표에만 참여한다.
리소스를 많이 먹지 않기 때문에, 전용 서버를 따로 둘 필요는 없다.
구성해보기
Primary DB와 Secondary DB 구성
둘 다 동일하다.
테스트 용으로 서버 1대에서 실행할 때에는 logpatth, dbpath, port, pidfilepath를 다르게 지정해야 한다.
ReplicaSet의 이름은 first로 지정해 보자.
12345678910111213141516171819 | # mongod.conf #where to log logpath=/var/lib/mongo/db1/mongod.log port=10001 dbpath=/var/lib/mongo/db1 # location of pidfile pidfilepath=/var/run/mongodb/mongod_repl1.pid # Listen to local interface only. Comment out to listen on all interfaces. bind_ip=127.0.0.1 # Replication Options # in replicated mongo databases, specify the replica set name here replSet=first |
Arbiter DB 구성
리소스를 최소한으로 설정하기 위해 smallfiles=true, noprealloc=true, oplogSize=1로 설정한다.
설정했을 때, 30메가 정도의 하드디스크를 먹었고,
안했을 때, 400메가 정도의 하드디스크를 차지하였다.
123456789101112131415161718192021222324252627282930 | # mongod.conf #where to log logpath=/var/lib/mongo/db3/mongod.log port=10003 dbpath=/var/lib/mongo/db3 smallfiles=true # location of pidfile pidfilepath=/var/run/mongodb/mongod_arb.pid # Listen to local interface only. Comment out to listen on all interfaces. bind_ip=127.0.0.1 # Disables write-ahead journaling nojournal=true # Disable data file preallocation. noprealloc=true # Replication Options # in replicated mongo databases, specify the replica set name here replSet=first # maximum size in megabytes for replication operation log oplogSize=1 |
실행해보기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | ## 실행 편의를 위해 머신 1대에서 실행하기 위해 ## port와 dbpath, logpath등을 변경하였다. ## dbpath, logpath에 지정한 폴더가 존재해야 한다. 없으면 만들어야 한다. 파일은 자동 생성되니 만들필요 없다.. ## Primary DB 실행 port:10001 $ mongod --config /etc/mongod_repl1 .conf ## Sencondary DB 실행 port:10002 $ mongod --config /etc/mongod_repl2 .conf ## Arbiter DB 실행 port:10003 $ mongod --config /etc/mongod_arb .conf ## Primary DB 접속해서 ReplicaSet 설정하기 $ mongo localhost:10001 /admin >db.runCommand({ "replSetInitiate" : { "_id" : "first" , "members" : [{ "_id" : 1, "host" : "localhost:10001" }, { "_id" : 2, "host" : "localhost:10002" } ]}}) first:PRIMARY> rs.add( 'localhost:10003' , true ) ## 설정 확인 first:PRIMARY> rs.status() { "set" : "first" , "date" : ISODate( "2014-06-23T08:10:24Z" ), "myState" : 1, "members" : [ { "_id" : 1, "name" : "localhost:10001" , "health" : 1, "state" : 2, "stateStr" : "SECONDARY" , "uptime" : 5086, "optime" : Timestamp(1403505938, 1), "optimeDate" : ISODate( "2014-06-23T06:45:38Z" ), "lastHeartbeat" : ISODate( "2014-06-23T08:10:23Z" ), "lastHeartbeatRecv" : ISODate( "2014-06-23T08:10:23Z" ), "pingMs" : 0, "syncingTo" : "localhost:10002" }, { "_id" : 2, "name" : "localhost:10002" , "health" : 1, "state" : 1, "stateStr" : "PRIMARY" , "uptime" : 6041, "optime" : Timestamp(1403505938, 1), "optimeDate" : ISODate( "2014-06-23T06:45:38Z" ), "electionTime" : Timestamp(1403505913, 1), "electionDate" : ISODate( "2014-06-23T06:45:13Z" ), "self" : true }, { "_id" : 3, "name" : "localhost:10003" , "health" : 1, "state" : 7, "stateStr" : "ARBITER" , "uptime" : 22, "lastHeartbeat" : ISODate( "2014-06-23T08:10:22Z" ), "lastHeartbeatRecv" : ISODate( "2014-06-23T08:10:23Z" ), "pingMs" : 0 } ], "ok" : 1 } |
테스트 해보기
Secondary DB가 원본 데이터를 잘 복사하는지 보자
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | ## Primary DB 접속해 테스트 데이터 넣기 $ mongo localhost:10002/ first:PRIMARY> use test switched to db test first:PRIMARY> for (var i = 0; i < 100; ++i) db.test_col.save({name:i}) WriteResult({ "nInserted" : 1 }) ## Secondary DB 접속해 원본 데이터를 복사했는지 확인 $ mongo localhost:10001/ first:SECONDARY> use test switched to db test first:SECONDARY> db.test_col. find ({}) error: { "$err" : "not master and slaveOk=false" , "code" : 13435 } ## slaveOk함수를 호출해야 읽기가 가능함 first:SECONDARY> rs.slaveOk() first:SECONDARY> db.test_col. find ({}) { "_id" : ObjectId( "53a7bd6c08c322644599914a" ), "name" : 0 } { "_id" : ObjectId( "53a7bd6c08c322644599914b" ), "name" : 1 } { "_id" : ObjectId( "53a7bd6c08c322644599914c" ), "name" : 2 } { "_id" : ObjectId( "53a7bd6c08c322644599914d" ), "name" : 3 } { "_id" : ObjectId( "53a7bd6c08c322644599914e" ), "name" : 4 } { "_id" : ObjectId( "53a7bd6c08c322644599914f" ), "name" : 5 } { "_id" : ObjectId( "53a7bd6c08c3226445999150" ), "name" : 6 } { "_id" : ObjectId( "53a7bd6c08c3226445999151" ), "name" : 7 } { "_id" : ObjectId( "53a7bd6c08c3226445999152" ), "name" : 8 } { "_id" : ObjectId( "53a7bd6c08c3226445999153" ), "name" : 9 } { "_id" : ObjectId( "53a7bd6c08c3226445999154" ), "name" : 10 } { "_id" : ObjectId( "53a7bd6c08c3226445999155" ), "name" : 11 } { "_id" : ObjectId( "53a7bd6c08c3226445999156" ), "name" : 12 } { "_id" : ObjectId( "53a7bd6c08c3226445999157" ), "name" : 13 } { "_id" : ObjectId( "53a7bd6c08c3226445999158" ), "name" : 14 } { "_id" : ObjectId( "53a7bd6c08c3226445999159" ), "name" : 15 } { "_id" : ObjectId( "53a7bd6c08c322644599915a" ), "name" : 16 } { "_id" : ObjectId( "53a7bd6c08c322644599915b" ), "name" : 17 } { "_id" : ObjectId( "53a7bd6c08c322644599915c" ), "name" : 18 } { "_id" : ObjectId( "53a7bd6c08c322644599915d" ), "name" : 19 } Type "it" for more ## 정상이군 |
Auto failover가 잘 되는지 보자
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | ## Primary DB에 접속해 디비 서버 종료 $ mongo localhost:10002 /admin MongoDB shell version: 2.6.2 connecting to: localhost:10002 /admin first:PRIMARY> db.shutdownServer() ## Sencondary DB에 접속해 자신이 Primary DB로 승격되었는지 확인 $ mongo localhost:10001 /admin MongoDB shell version: 2.6.2 connecting to: localhost:10001 /admin first:PRIMARY> rs.status() { "set" : "first" , "date" : ISODate( "2014-06-23T08:33:50Z" ), "myState" : 1, "members" : [ { "_id" : 1, "name" : "localhost:10001" , "health" : 1, "state" : 1, "stateStr" : "PRIMARY" , "uptime" : 7083, "optime" : Timestamp(1403511736, 100), "optimeDate" : ISODate( "2014-06-23T08:22:16Z" ), "electionTime" : Timestamp(1403512372, 1), "electionDate" : ISODate( "2014-06-23T08:32:52Z" ), "self" : true }, { "_id" : 2, "name" : "localhost:10002" , "health" : 0, "state" : 8, "stateStr" : "(not reachable/healthy)" , "uptime" : 0, "optime" : Timestamp(1403511736, 100), "optimeDate" : ISODate( "2014-06-23T08:22:16Z" ), "lastHeartbeat" : ISODate( "2014-06-23T08:33:46Z" ), "lastHeartbeatRecv" : ISODate( "2014-06-23T08:32:44Z" ), "pingMs" : 0 }, { "_id" : 3, "name" : "localhost:10003" , "health" : 1, "state" : 7, "stateStr" : "ARBITER" , "uptime" : 1427, "lastHeartbeat" : ISODate( "2014-06-23T08:33:48Z" ), "lastHeartbeatRecv" : ISODate( "2014-06-23T08:33:49Z" ), "pingMs" : 0 } ], "ok" : 1 } |
Auto Failover 동작 테스트
S와 A의 수가 장애극복 처리에 어떤 영향을 끼치는지,
S와 A서버에 장애가 발했을 때, P서버에도 장애가 발생하면 어떻게 되는지 테스트 해보았다.
Primary = P, Secondary = S, Arbiter = A DB Type = O(alive) or X(dead) | 동작 여부 |
P = X S = O A = O | O |
P = X S = O A = X | X |
P = X S = O S = O A = O | O |
P = X S = O S = O A = X | X |
P = X S = O S = X A = O | X |
P = X S = O A = O A = O | O |
P = X S = O A = O A = X | X |
P = X S = O S = O S = O A = O | O |
P = X S = O S = O S = X A = O | O |
P = X S = O S = O S = X A = X | X |
P = X S = O S = X S = X A = X | X(P가 S로 자동으로 변경) |
P = X S = O S = O A = O A = O | O |
P = X S = O S = O A = X A = X | X |
P = X S = O S = X A = X A = X | X(P가 S로 자동으로 변경) |
P = X S = O S = O S = O A = O A = O | O |
P = X S = O S = X S = O A = O A = O | O |
P = X S = O S = X S = O A = O A = X | X |
P = X S = O S = O S = O A = X A = X | X |
P = X S = O S = X S = X A = O A = X | X(P가 S로 자동으로 변경) |
테스트 결론
A와 S에 속한 맴버 중 과반수에 장애가 발생한다면, P는 S로 자동으로 변경됨.
ReplicaSet 전체 맴버 중 살아있는 수가 과반수가 아니면 장애극복이 이루어지지 않는다. 즉, S가 2대 이상이 살았어도 살아남은 수가 과반수가 아니면 장애극복이 안된다.
'엔지니어 > Linux' 카테고리의 다른 글
node.js 설치 (0) | 2016.05.26 |
---|---|
iptables-xml (0) | 2016.05.26 |
텔레그램을 커맨드 라인으로 사용하기, Telegram_cli (0) | 2016.05.26 |
DRBD (0) | 2016.05.26 |
nginx upstream (0) | 2016.05.26 |