1. 독립 실행형 모드에서 멤버 시작
- 많은 유지 보수 작업은 쓰기와 관련되어 있어 Secondary에서 수행될 수 없으며, 애플리케이션 성능에 영향을 미치기 때문에 Primary에서 수행하면 안 됨
- 따라서 해당 절에서는 독립 실행형 모드 서버 시작을 자주 언급함
- 이는 멤버가 복제 셋의 멤버가 아닌 독립 실행형 서버로 재시작함을 의미
- 독립 실행형 모드에서 멤버를 시작하려면 먼저 명령행 인수를 확인해야 하며 인수는 다음과 같다고 가정
- 해당 서버에서 유지보수를 수행하려면 replSet 옵션 없이 서버를 재시작하면 되며 이는 일반적인 독립 실행형 mongod처럼 읽기와 쓰기가 가능하게 해 줌
- 복제 셋에 있는 다른 서버에서 해당 서버와 통신하기를 원치 않으므로 다른 멤버들이 서버를 발견하지 못하도록 서버가 다른 포트로 수신하게 함
- 마지막으로, 서버 데이터를 조작하려고 이런 방식으로 시작하려고 dbpath는 그대로 유지
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> db.serverCmdLineOpts() | |
{ | |
"argv": [ "mongod", "-f", "/var/lib/mongod.conf" ], | |
"parsed": { | |
"replSet": "mySet", | |
"port": "27017", | |
"dbpath": "/var/lib/db" | |
}, | |
"ok": 1 | |
} |
- 먼저 mongo 셸에서 서버를 종료한 뒤 운영체제 셸에서 replSet 매개변수 없이 다른 포트에서 mongod를 시작하면 독립 실행형 서버로 구동 가능
- 독립 실행형 서버로 연결을 위한 포트는 30000번
- 복제 셋의 다른 멤버는 27017번 포트로 해당 서버에 접속을 시도하고, 곧 서버가 다운됐다고 추정하게 됨
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 서버 종료 | |
> db.shutdownServer | |
// 독립 실행형 서버 구동 | |
$ mongod --port 30000 --dbpath /var/lib/db |
- 서버에서 유지 보수 수행을 마치면, 서버를 종료하고 원래 옵션으로 재시작 가능
- 서버는 유지 보수 모드 기간 동안 놓친 연산들을 복제해 복제 셋의 다른 멤버와 자동으로 동기화 진행
2. 복제 셋 구성
- 복제 셋 구성은 항상 local.system.replset 컬렉션의 도큐먼트에 보관되며 해당 도큐먼트는 복제 셋의 모든 멤버에서 같음
- 절대 update를 이용해 도큐먼트를 변경하지 말고 항상 rs 보조자나 replSetReconfig 명령을 통해 업데이트하는 것을 권장
2.1 복제 셋 생성하기
- 멤버로 만들 mongod들을 시작하고 그중 하나에 rs.initiate()를 사용해 구성 정보를 전달함으로써 복제 셋을 생성함
- 복제 셋의 한 멤버에서만 rs.initiate를 호출 가능하며 멤버는 구성 정보를 받아 다른 멤버들에 전달함
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> var config = { | |
"_id": <setName>, | |
"members": [ | |
{"_id": 0, "host": <host1>}, | |
{"_id": 1, "host": <host2>}, | |
{"_id": 2, "host": <host3>} | |
] | |
} | |
> rs.initiate(config) |
2.2 복제 셋 멤버 교체하기
- 복제 셋에 새로운 멤버를 추가할 때는 데이터 디렉토리에 아무것도 존재하지 않거나 다른 멤버 데이터의 복제본이 있어야 함
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 새로운 멤버 추가 | |
> rs.add("spock:27017") | |
// 복잡한 멤버 구성을 도큐먼트 형태로 명시 | |
> rs.add({"host": "spock:27017", "priority": 0, "hidden": true}) | |
// "host" 필드를 이용해 멤버 제거 | |
> rs.remove("spock:27017") |
- 재구성을 통해 멤버의 설정을 바꿀 수 있으며 멤버의 설정을 바꾸는 데는 다음과 같은 제약 사항이 있음
- 멤버의 "_id"는 변경할 수 없음
- 재구성 정보를 전달하려는 멤버의 우선순위를 0으로 할 수 없음
- 아비터에서 아비터가 아닌 것으로 변경할 수 없으며, 반대도 마찬가지
- 멤버의 "buildIndexes"를 falsae에서 true로 변경 불가
- 멤버의 "host" 필드는 변경할 수 있으며 호스트명을 변경하려면 다음과 같이 해야 함
- 호스트 정보를 잘 못 명시했을 때 다음과 같이 간단히 변경 가능
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> var config = rs.config() | |
> config.members[0].host = "spock:27017" | |
spock:27017 | |
> rs.reconfig(config) |
2.3 큰 복제 셋 만들기
- 복제 셋에서 멤버는 50개, 투표 멤버는 7개로 제한됨
- 이는 다른 멤버에 하트비트를 보내는 데 필요한 네트워크 트래픽량을 줄이고 선출에 걸리는 시간을 제한하기 위함
- 멤버가 7개 이상인 복제 셋을 생성한다면, 모든 추가적인 멤버는 투표권이 0개여야 하며 이를 수행하려면 멤버 구성 정보에 다음처럼 명시해야 함
- 이는 해당 멤버들이 거부권을 갖더라도 선출 과정에서 투표권을 행사하는 것을 방지함
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> rs.add({"_id": 7, "host": "server-7:27017", "votes": 0}) |
2.4 재구성 강제하기
- 복제 셋의 과반수를 영구적으로 잃으면, Primary가 없는 상태에서 설정을 재구성할 필요가 있음
- 이때 Secondary에 재구성 명령을 보냄으로써 복제 셋 재구성을 강제할 수 있음
- 셸에서 Secondary에 연결하고 "force" 옵션을 이용해 재구성 명령을 전달함으로써 재구성 가능
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> rs.reconfig(config, {"force": true}) |
- 강제 재구성은 일반 재구성과 같은 규칙을 따르며, 사용자는 유효하고 잘 구성된 구성 정보를 올바른 옵션으로 보내야 함
- "force" 옵션은 유효하지 않은 구성 정보를 허용하지 않고, 다만 Secondary가 재구성 정보를 받아들이도록 허용함
- 강제 재구성은 복제 셋 `version` 번호를 크게 높이는데 이는 재구성 정보가 네트워크 파티션 양쪽에 있을 때 버전 번호가 충돌하지 않도록 하기 위함
- 수천 단위를 건너뛰는 것이 정상
- Secondary는 재구성 정보를 받으면 자신의 구성 정보를 갱신하고 새로운 구성 정보를 다른 멤버에 전달함
- 복제 셋의 다른 멤버는 정보를 전송하는 서버를 현재 구성 정보의 멤버로 인식하면 구성의 변화만을 찾아내므로 일부 멤버가 호스트명을 변경하면 예전 호스트명을 그대로 갖는 멤버를 강제 재구성해야 함
- 모든 멤버가 새로운 호스트명을 가지면 복제 셋의 각 멤버를 다운시키고, 새로운 멤버를 독립 실행형 모드로 시작한 뒤 local.system.replset 도큐먼트를 수동으로 변경하고 멤버를 재시작함
3. 멤버 상태 조작
- 유지 보수를 수행할 때나 부하에 대한 응답으로 수동으로 멤버 상태를 변경하는 방법은 여러 가지지만
- 멤버가 Primary가 되도록 강제하려면 복제 셋을 상황에 맞게 구성하는 것 외에는 방법이 없음
3.1 Primary에서 Secondary로 변경하기
- stepDown 함수를 이용하면 Primary를 Secondary로 강등할 수 있음
- Primary를 60초 동안 SECONDARY 상태로 만듦
- 해당 기간 동안 다른 Primary가 선출되지 않으면 Secondary 상태로 변했던 Primary는 재선출을 시도할 수 있음
- 더 길거나 짧은 시간 동안 Secondary 상태로 남겨두려면 몇 초간 SECONDARY 상태로 머물게 할지 지정함
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> rs.stepDown() // Primary -> Secondary | |
> rs.stepDown(600) // Primary -> Secondary 10분동안 |
3.2 선출 방지하기
- Primary 상에서 유지 보수 작업을 수행해야 하고, 그 사이에 자격이 있는 다른 멤버가 Primary가 되지 않도록 하려면, 각각의 멤버에 freeze 명령을 실행함으로써 Secondary 상태에 머물게 해야 함
- 마찬가지로 멤버는 몇 초 동안 Secondary 상태로 유지됨
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> rs.freeze(10000) |
- 시간이 경과하기 전에 Primary에서 수행 중인 유지 보수를 완료해 다른 멤버의 freeze 상태를 해제하려면, 각 멤버에 타임아웃을 0초로 지정해 명령을 다시 실행
- freeze 상태가 아닌 멤버는 원한다면 선출을 실시할 수 있고 강등했던 Primary도 rs.freeze(0)를 사용해 freeze 상태를 해제할 수 있음
4. 복제 모니터링
- 복제 셋의 상태를 모니터링하는 것은 중요하며 모든 멤버가 정상적으로 기동 했는지, 멤버가 어떤 상태인지, 그리고 복제가 얼마나 최신 상태인지 모니터링함
- 몇 가지 명령으로 복제 셋 정보를 볼 수 있음
- 아틀라스, 클라우드 매니저, 옵스 매니저를 포함한 몽고DB 호스팅 서비스와 관리 도구는, 복제를 모니터링하는 메커니즘과 주요 복제 지표에 대한 대시보드를 제공
- 복제와 관련된 문제는 일시적일 때가 많음
- 서버가 다른 서버에 도달할 수 없었다가 다시 도달할 수 있게 될 때가 있으며 로그를 확인하면 비슷한 문제를 쉽게 볼 수 있음
- 로그가 어디에 저장되는지 확인하고, 로그가 잘 저장되며 해당 로그에 접근할 수 있음을 확실히 확인해야 함
4.1 상태 정보 가져오기
- 복제 셋의 모든 멤버의 정보를 얻는 데 가장 유용한 명령은 replSetGetStatus
- 셸에는 해당 명령에 사용할 수 있는 보조자가 있음
- 가장 유용한 필드들은 다음과 같음
- "self": rs.status()가 실행된 멤버에만 존재하며, 예제에는 server-1
- "stateStr": 서버의 상태를 나타내는 문자열
- "uptime": 멤버에 도달할 수 있었던 시간 혹은 해당 서버가 "self" 멤버를 위해 시작된 이후부터의 시간
- "optimeDate": 각 멤버의 oplog에서 마지막 연산 수행 시각을 의미; 이는 하트비트에 의해 보고된 각 멤버의 상태이고, 보고된 연산 수행 시각은 몇 초 정도 차이가 날 수 있음
- "lastHeartbeat": 서버가 "self" 멤버로부터 하트비트를 받은 시간, 네트워크 문제가 있거나 서버가 분주하면 해당 시간은 2초 전보다 길어질 수 있음
- "pingMs": 해당 서버에 대한 하트비트에 걸린 평균 실행 시간, 어느 멤버로부터 동기화할지 결정하는 데 사용
- "errmsg": 멤버가 하트비트 요청에 반환하기로 선택한 모든 상태 메시지, 단지 정보 전달용이며 오류 메시지는 아님
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> rs.status() | |
{ | |
"set": "replset", | |
"date": ISODate("..."), | |
"myState": 1, | |
// 중략 | |
"members": [ | |
{ | |
"_id": 0, | |
"name": "m1.example.net:27017", | |
"health": 1, | |
"state": 1, | |
"stateStr": "PRIMARY", | |
"uptime": 269, | |
"optime": { | |
"ts": Timestamp("..."), | |
"t": NumberLong(1) | |
}, | |
"optimeDate": ISODate("..."), | |
"infoMessage": "could not find member to sync from", | |
"electionTime": Timestamp(..., 1), | |
"electionDate": ISODate("..."), | |
"configVersion": 1, | |
"self": true | |
}, | |
{ | |
"_id": 1, | |
"name": "m2.example.net:27017", | |
"health": 1, | |
"state": 2, | |
"stateStr": "SECONDARY", | |
"uptime": 14, | |
"optime": { | |
"ts": Timestamp(...), | |
"t": NumberLong(1) | |
}, | |
// 중략 | |
"lastHeartbeat": ISODate("..."), | |
"lastHearbeatRecv": ISODate("..."), | |
"pingMs": NumberLong(0), | |
"syncingTo": "m3.example.net:27017", | |
"configVersion": 1 | |
}, | |
// 중략 | |
], | |
"ok": 1 | |
} |
4.2 복제 그래프 시각화하기
- Secondary에서 rs.status()를 시행하면 `syncingTo`라는 최상위 필드를 확인 가능하며 이는 멤버가 복제를 수행하는 호스트를 제공
- 복제 셋의 각 멤버에서 replSetGetStatus 명령을 실행하면 복제 그래프를 알아낼 수 있음
- 아래 예제는 server1이 server1에 대한 연결, server2가 server2에 대한 연결이라 가정했음
- server0은 server1의 복제 소스
- server1은 server2와 server3의 복제 소스
- server2는 server4의 복제 소스
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> server1.adminCommand({replSetGetStatus: 1})['syncingTo'] | |
server0:27017 | |
> server2.adminCommand({replSetGetStatus: 1})['syncingTo'] | |
server1:27017 | |
> server3.adminCommand({replSetGetStatus: 1})['syncingTo'] | |
server1:27017 | |
> server4.adminCommand({replSetGetStatus: 1})['syncingTo'] | |
server2:27017 |
- 몽고DB는 핑 시간을 기준으로 동기화할 대상을 결정
- 멤버는 다른 멤버에 하트비트를 보낼 때, 요청이 처리되기까지 걸리는 시간을 재며 몽고DB는 이러한 평균 실행 시간을 보관함
- 동기화할 멤버를 선택할 때, 멤버는 가장 가깝고 복제에서 자신보다 앞서 있는 멤버를 찾으므로 복제 순환이 발생하지 않고 멤버는 자신보다 앞서 있는 Primary나 Secondary만 복제함
- 그러므로 만약 Secondary가 있는 데이터 센터에 새로운 멤버를 투입하면 Primary가 있는 데이터 센터의 멤버보다 Secondary가 있는 데이터 센터와 다른 멤버와 동기화할 가능성이 높으므로 WAN 트래픽을 최소화 시킴
- 그러나 자동 복제 사슬 (automatic replication chaining)에는 몇 가지 단점이 있음
- 복제 홉이 많을수록 모든 서버에 쓰기를 복제하는 데 시간이 좀 더 오래 걸림
- ex) 모든 멤버가 하나의 데이터 센터에 있는 상황에서 새로운 멤버를 추가할 때 네트워크 속도가 예상치 않게 변하면, MongoDB가 모든 복제본을 일렬로 복제하는 형태가 될 수 있으며 이런 경우, replSetSyncFrom 명령을 사용해 각 멤버가 복제할 대상을 직접 지정할 수 있음
- 이를 통해 사슬 구조로 각 Secondary가 앞에 있는 Secondary보다 약간씩 느리게 동기화되도록 설정할 수 있으며, 이는 복제 지연을 단계적으로 분산시키는 바람직한 방법이 될 수 있음
4.3 복제 루프
- 복제 루프는 모든 멤버가 다른 멤버로부터 복제를 수행하는 상태
- ex) A는 B로부터 동기화하고, B는 C로부터, C는 다시 A로부터 동기화하는 상태
- 모든 복제 루프 멤버는 Primary가 될 수 없으므로, 멤버들은 복제를 위한 새로운 명령을 받을 수 없고 뒤쳐지게 됨
- 멤버가 동기화할 멤버를 자동으로 고를 때는 복제 루프가 발생하지 않음
- 그러나 replSetSyncFrom 명령을 이용해 복제 루프를 강제로 수행할 수 있는데 수동으로 동기화 대상을 바꾸기 전에 rs.status() 결과를 주의 깊게 검사하고, 루프를 만들지 않도록 주의해야 함
4.4 복제 사슬 비활성화하기
- 복제 사슬은 Secondary가 또 다른 Secondary와 동기화할 때 발생하며 멤버는 자동으로 다른 멤버와 동기화하도록 결정할 수 있음
- "chaingingAllowed" 설정을 false로 변경해 모든 멤버가 Primary와 동기화하게 함으로써 복제 사슬을 사용하지 않도록 설정 가능
- 단, Primary가 이용 불가능한 상태가 되면 Secondary와 동기화하게 됨
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> var config = rs.config() | |
// (존재하지 않는다면) 하위 객체 생성 | |
> config.settings = config.settings || {} | |
> config.settings.chainingAllowed = false | |
> rs.recofing(config) |
4.5 지연 계산하기
- 복제를 추적하는 지표로, Secondary가 얼마나 Primary를 잘 따라잡는지가 중요함
- 지연은 Secondary가 얼마나 뒤처져 있는지 나타내는데, Primary가 마지막으로 수행한 연산과 Secondary가 마지막으로 적용한 연산의 타임스탬프의 차이를 의미함
- rs.status()를 사용해 멤버의 복제 상태를 볼 수 있으며, rs.printReplicationInfo()나 rs.printSlaveReplicationInfo()를 실행해 빠른 요약을 얻을 수 있음
- rs.printReplicationInfo()는 연산의 크기와 날짜 범위를 포함하는 Primary에 oplog의 요약 정보를 제공함
- 아래 예제에서 oplog는 약 10MB이며 약 1시간의 연산까지만 수행 가능
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> rs.printReplicationInfo(); | |
configured oplog size: 10.48576MB | |
log length start to end: 3590 secs (1.00hrs) | |
oplog first event time: Tue Apr 10 2025 09:27:57 GMT-0400 (EDT) | |
oplog last event time: Tue Apr 10 2025 10:27:57 GMT-0400 (EDT) | |
now: Tue Apr 10 2025 10:27:57 GMT-0400 (EDT) |
- 실제 배포라면 oplog가 더 커야 하고 로그 길이는 적어도 전체적으로 재동기화하는 데 걸리는 시간만큼 길게 설정하는 것을 권장
- 그러면 초기 동기화를 완료하기 전에 Secondary가 oplog의 끝에서 밀려나는 상황은 생기지 않음
- 다음 예제와 같이 rs.printSlaveReplicationInfo() 함수를 사용해 각 멤버의 syncedTo 값과 마지막 oplog 항목이 각 Secondary에 기록된 시간을 가져올 수 있음
- 복제 셋 멤버의 지연은 절대적인 시간이 아니라 Primary를 기준올 상대적으로 계산됨
- 보통은 문제가 되지 않지만 쓰기 작업을 매우 드물게 수행하는 시스템에서는 유령 복제 지연인 `트래픽의 급격한 증가`를 발생시킬 수 있음
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> rs.printSlaveReplicationInfo(); | |
source: m1.example.net:27017 | |
syncedTo: Tue Apr 10 2025 10:27:47 GMT-0400 (EDT) | |
0 secs (0 hrs) behind the primary | |
source: m2.example.net:27017 | |
syncedTo: Tue Apr 10 2025 10:27:43 GMT-0400 (EDT) | |
0 secs (0 hrs) behind the primary | |
source: m3.example.net:27017 | |
syncedTo: Tue Apr 10 2025 10:27:39 GMT-0400 (EDT) | |
0 secs (0 hrs) behind the primary |
4.6 Oplog 크기 변경하기
- Primary의 oplog는 유지 보수 시간으로 여겨짐
- Primary의 oplog 길이가 한 시간 정도라면, 잘 못된 부분을 고칠 수 있는 시간은 한 시간 정도라는 의미
- 따라서 뭔가가 잘못될 때 약간의 숨 쉴 틈이 있으려면 일반적으로 며칠에서 1주 정도 데이터를 보유할 수 있는 oplog가 바람직함
- 아쉽게도 oplog가 얼마나 지속될지는 가득 차기 전까지 쉽게 알 수 없음
- 와이어드타이거 스토리지 엔진 사용 시 서버가 실행되는 동안 oplog 크기를 조정할 수 있음
- oplog의 크기를 늘리려면 다음 단계를 수행해야 함
- 복제 셋 멤버에 연결하고 인증이 활성화됐다면 local 데이터베이스를 수정할 권한이 있는 사용자를 사용
- oplog의 현재 크기를 확인
- 복제 셋 멤버의 oplog 크기를 변경
- 마지막으로 oplog의 크기를 줄였다면 compact를 실행해 할당된 디스크 공간을 회수해야 할 수도 있지만 대상 멤버가 Primary인 동안에는 실행해서는 안 됨
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// local 데이터베이스 수정할 권한이 있는 ㄴ사용자를 사용 | |
// oplog 현재 크기 확인 | |
> use local | |
> db.oplog.rs.stats(1024*1024).maxSize | |
// 복제 셋 멤버의 oplog 크기 변경 | |
> db.adminCommand({replSetResizeOplog: 1, size: 16000}) |
- 일반적으로 oplog의 크기는 줄이면 안 됨
- oplog 크기가 수개월이더라도 일반적으로 디스크 공간을 충분하며 램이나 CPU 같은 귀중한 리소스를 소모하지 않음
4.7 인덱스 구축하기
- Primary에 인덱스 구축을 전송하면 Primary는 정상적으로 인덱스를 구축하며, Secondary는 "build index" 연산을 복제할 때 인덱스를 구축함
- 이는 인덱스를 구축하는 가장 쉬운 방법이긴 하지만, 인덱스 구축은 멤버를 이용 불가능한 상태로 만들 수도 있는 리소스 집약적인 연산
- 만약 모든 Secondary가 동시에 인덱스를 구축하기 시작한다면 복제 셋의 거의 모든 멤버는 인덱스 구축이 완료될 때까지 오프라인 상태가 되며 해당 과정은 복제 셋에만 해당됨
- 따라서 애플리케이션에 대한 영향을 최소화하려면 인덱스는 한 번에 한 멤버씩 구축하는 것이 바람직하며 이를 수행하려면 다음과 같이 수행해야 함
- Secondary를 종료함
- 종료한 Secondary를 독립 실행형 서버로 재시작
- 재시작한 서버에 인덱스 구축
- 인덱스 구축이 완료되면 서버를 복제 셋 멤버로 재시작하며 멤버를 재시작할 때 명령행 옵션이나 구성 파일에 disableLogicalSessionCacheRefresh 매개변수가 있으면 제거해야 함
- 복제 셋의 각 Secondary에 1단계부터 4단계까지 반복함
- 이제 셋에서 Primary를 제외한 모든 멤버의 인덱스가 구축되었고 다음 두 가지 선택지 중 실제 시스템에 가장 적게 영향을 미치는 방법을 선택해야 함
- Primary에 인덱스를 구축하는데 트래픽이 적을 때 "off" 시간을 가질 수 있다면 이때 구축하는 것을 권장
- 읽기 선호도를 수정함으로써 구축이 진행 중일 때 Secondary로 더 많은 부하를 보내도록 일시적으로 경로를 변경할 수 있음
- Primary는 인덱스 구축을 Secondary에 복제하지만, Secondary는 이미 인덱스가 있으므로 어떤 연산 작업도 발생하지 않음
- Primary를 강등한 후 앞서 설명한 2~4 단계를 거침
- 해당 방식에는 장애 조치가 필요하지만 기존 Primary가 인덱스를 구축하는 동안 정상적으로 작동하는 Primary가 있음
- 인덱스 구축이 완료된 후 기존 Primary를 복제 셋에 재도입할 수 있음
- Primary에 인덱스를 구축하는데 트래픽이 적을 때 "off" 시간을 가질 수 있다면 이때 구축하는 것을 권장
- 위 방법으로 Secondary에서 다른 복제 셋 멤버의 인덱스와 다른 인덱스를 구축할 수 있으며 이는 오프라인 처리에 유용할 수 있음
- 다만 다른 멤버는 절대 Priamry가 될 수 없으며 우선순위가 항상 0임
- 고유 인덱스를 구축할 때는 Primary가 중복 삽입을 하지 않아야 하며, 인덱스를 Primary에 먼저 구축해야 함
- 그렇지 않으면 Primary는 중복 삽입을 하게 되고 Secondary에 복제 오류를 발생시킴
- 이러한 오류가 발생하면 Secondary는 스스로 종료하며, 독립 실행형으로 재시작해 고유 인덱스를 삭제한 뒤 재시작해야 함
4.8 한정된 예산에서 복제하기
- 고성능 서버를 두 개 이상 구하기 어렵다면, 적은 램과 CPU, 속도가 느린 디스크 입출력을 갖는 재해 복구용 Secondary 서버를 권장
- 좋은 서버는 항상 Primary로 쓰고, 상대적으로 값싼 서버는 절대 클라이언트 트래픽을 처리하지 않게 해야 함
- 다음은 값싼 서버를 설정하기 위한 옵션
- "priority": 0 => 해당 서버가 절대 Primary가 되지 않도록 설정
- "hidden": true => 클라이언트가 해당 Secondary에 읽기 요청을 절대 보내지 않도록 설정
- "buildIndexes": false => 선택적이지만 해당 서버가 처리해야 하는 부하를 상당히 줄일 수 있음; 해당 서버로부터 복원할 경우 인덱스를 재구축해야 함
- "votes": 0 => 서버가 두 개뿐이라면 Secondary의 "votes"를 0으로 설정해서 해당 서버가 다운되더라도 Primary가 Primary로 유지 되도록 함; 세 번째 서버가 있다면 해당 서버의 "votes"를 0으로 설정하는 대신 아비터를 실행
참고
몽고DB 완벽 가이드 3판 - 한빛미디어
반응형
'DB > 몽고DB 완벽 가이드 3판' 카테고리의 다른 글
[15장] 샤딩 구성 (0) | 2025.05.16 |
---|---|
[14장] 샤딩 소개 (0) | 2025.05.16 |
[12장] 애플리케이션에서 복제 셋 연결 (0) | 2025.04.25 |
[11장] 복제 셋 구성 요소 (0) | 2025.04.24 |
[10장] 복제 셋 설정 (0) | 2025.04.22 |