티스토리 뷰

DB/MongoDB

[MongoDB] 복제 셋 관리

snail voyager 2023. 8. 8. 17:03
728x90
반응형

13.1 독립 실행형 모드에서 멤버 시작

  • 유지 보수 작업은 (쓰기와 관련) 세컨더리에서 수행 불가
  • 애플리케이션 성능에 영향을 미치기 때문에 프라이머리에서 수행하면 안됨
  • 복제 셋의 멤버가 아닌 독립 실행형 서버로 재시작해야함
  • 이 서버에서 유지 보수를 수행하려면 replSet 옵션 없이 서버를 재시작
  • 다른 서버에서 통신하지 않도록 다른 포트로 수신
  • 서버의 데이터를 어떤 방식으로든 조작하기 위해 dppath는 그대로 유지
> db.serverCmdLineOpts()
{
    "argv" : [ "mongod", "-f", "/var/lib/mongod.conf" ],
    "parsed" : {
        "replSet": "mySet",
        "port": "27017",
        "dbpath": "/var/lib/db"
    },
    "ok" : 1
}

> db.shutdownServer()	//서버 종료

$ mongod --port 30000 --dbpath /var/lib/db	//replSet 매개변수 없이 다른 포트에서 실행

13.2 복제 셋 구성

  • 복제 셋 구성은 항상 local.system.replset 컬렉션의 도큐먼트에 보관
  • 복제 셋의 모든 멤버에서 같음
  • update 를 이용해 도큐먼트를 변경하지 말고, rs 보조자나 replSetReconfig 명령 사용

13.2.1 복제 셋 생성하기

  • 멤버로 만들 mongod를 시작하고 그 중 하나에 rs.initiate() 를 사용해 구성 정보를 전달함으로써 복제 셋 생성
  • 복제 셋의 한 멤버에서만 rs.initiate() 호출 가능
> var config = {
... "_id" : <setName>,
... "members" : [
...     {"_id" : 0, "host" : <host1>},
...     {"_id" : 1, "host" : <host2>},
...     {"_id" : 2, "host" : <host3>}
... ]}
> rs.initiate(config)

13.2.2 복제 셋 멤버 교체하기

  • 새로운 멤버를 추가할 때는 데이터 디렉터리에 아무것도 존재하지 않거나 (초기 동기화 수행)
  • 다른 멤버 데이터의 복제본이 있어야함
> rs.add("spock:27017")	//새로운 멤버 추가

> rs.add({"host" : "spock:27017", "priority" : 0, "hidden" : true})	//도큐먼트로 멤버 구성

> rs.remove("spock:27017")	//"host" 필드를 이용해서 멤버 제거
  • 멤버의 설정을 바꾸는데 제약 사항
    • 멤버의 "_id"는 변경 불가
    • 재구성 정보를 전달하려는 멤버(일반적으로 프라이머리)의 우선순위를 0으로 할 수 없음
    • 아비터에서 아비터가 아닌 것으로 변경 불가, 반대도 불가
    • 멤버의 "buildIndexes" 를 false에서 true로 변경 불가
  • 멤버의 host 필드는 변경 가능
> var config = rs.config()
> config.members[0].host = "spock:27017"
spock:27017
> rs.reconfig(config)

13.2.3 큰 복제 셋 만들기

  • 복제 셋에서 멤버는 50개, 투표 멤버는 7개로 제한
  • 다른 멤버에 하트비트를 보내는 데 필요한 네트워크 트래픽량을 줄이고 선출에 걸리는 시간을 제한하기 위함
> rs.add({"_id" : 7, "host" : "server-7:27017", "votes" : 0})	//멤버들이 선출 과정에서 투표권을 행사하는 것을 방지

13.2.4 재구성 강제하기

  • 복제 셋이 과반수를 영구적으로 잃으면, 프라이머리가 없는 상태에서 설정을 재구성할 필요
  • 세컨더리에 재구성 명령을 보내 복제 셋 재구성을 강제
> rs.reconfig(config, {"force" : true})
  • "force" 옵션은 유효하지 않은 구성 정보를 허용하지 않고, 세컨더리가 재구성 정보를 받아들이도록 허용
  • 강제 재구성은 복제 셋 "version" 번호를 크게 높임.
    재구성 정보가 네트워크 파티션 양쪽에 있을 때 버전 번호가 충돌하지 않도록 하기 위함
  • 일부 멤버가 호스트명을 변경하면 예전 호스트명을 그대로 갖는 멤버를 강제 재구성
  • 모든 멤버가 새로운 호스트명을 가지면 복제 셋의 각 멤버를 다운시키고,
    새로운 멤버를 독립 실행형 모드로 시작한 뒤,
    local.system.replset 도큐먼트를 수동으로 변경하고 멤버를 재시작

13.3 멤버 상태 조작

13.3.1 프라이머리에서 세컨더리로 변경하기

  • stepDown 함수를 이용하면 프라이머리를 세컨더리로 강등
  • 강등 기간동안 드란 프라이머리가 선출되지 않으면 세컨더리로 변했던 프라이머리는 재선출 시도
> rs.stepDown()	//프라이머리를 60초 동안 세컨더리로 만든다
> rs.stepDown(600) // 10 minutes

13.3.2 선출 방지하기

  • 프라이머리상에서 유지 보수 작업을 수행해야 하고, 그 사이에 자격이 있는 다른 멤버가 프라이머리가 되지 않게 하려면
  • freeze 명령으로 세컨더리 상태에 머물게 함
  • freeze 상태를 해제하려면 타임아웃을 0초로 지정
  • 강등했던 프라이머리도 rs.freeze(0)으로 해제 가능
> rs.freeze(10000)
> rs.freeze(0)

13.4 복제 모니터링

13.4.1 상태 정보 가져오기

복제 셋의 모든 멤버의 정보를 얻는 명령어 replSetGetStatus

> rs.status()

13.4.2 복제 그래프 시각화

  • rs.status() 결과의 syncingTo 필드 : 복제를 수행하는 호스트
  • 복제 셋의 각 멤버에서 replSetGetStatus 명령으로 복제 그래프를 시각화
  • server0 <- server1 <- server2 <- server4
> 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
  • 핑 시간을 기준으로 동기화할 대상 결정
  • 동기화할 멤버를 선택할 때, 멤버는 가장 가깝고 복제에서 자신보다 앞서 있는 멤버를 찾음 (복제 순환 발생 X)
  • 다른 데이터센터의 프라이머리보다 같은 데이터 센터에 있는 멤버를 동기화
  • 복제 사슬이 길어질수록 모든 멤버가 데이터의 복제본을 얻는데 오래 걸림
  • replSetSyncFrom, rs.syncFrom() 으로 멤버의 복제 소스를 수정하여 문제 해결
> secondary.adminCommand({"replSetSyncFrom" : "server0:27017"})

13.4.3 복제 루프

  • 모든 멤버가 다른 멤버로부터 복제를 수행하는 상태
  • A <- B <- C <- A
  • 모든 복제 루프는 프라이머리가 될 수 없으므로, 멤버들은 복제를 위한 새로운 명령을 받을 수 없고 뒤쳐짐
  • replSetSyncFrom 명령으로 복제 소스를 수정할 때 복제 루프 발생

13.4.4 복제 사슬 비활성화

  • 복제 사슬은 세컨더리가 또 다른 세컨더리와 동기화할 때 발생
  • chainingAllowed 를 false로 모든 멤버는 프라이머리와 동기화
> var config = rs.config()
> config.settings = config.settings || {}
> config.settings.chainingAllowed = false
> rs.reconfig(config)

13.4.5 지연 계산하기

  • 복제를 추적하는 지표로 세컨더리가 얼마나 프라이머리를 잘 따라잡는지 중요
  • 지연은 세컨더리가 얼마나 뒤처지는지 프라이머리의 마지막 수행 연산과 세컨더리의 마지막 적용 연산의 타임스탬프 차이
  • rs.printReplicationInfo()는 연산의 크기와 날짜 범위를 포함하는 프라이머리 oplog의 요약정보
> rs.printReplicationInfo();
    configured oplog size:   10.48576MB
    log length start to end: 3590 secs (1.00hrs)
    oplog first event time:  Tue Apr 10 2018 09:27:57 GMT-0400 (EDT)
    oplog last event time:   Tue Apr 10 2018 10:27:47 GMT-0400 (EDT)
    now:                     Tue Apr 10 2018 10:27:47 GMT-0400 (EDT)
  • rs.printSlaveReplicationInfo()는 각 멤버의 syncedTo 값과 마지막 oplog 항목이 세컨더리에 기록된 시간
> rs.printSlaveReplicationInfo();
source: m1.example.net:27017
    syncedTo: Tue Apr 10 2018 10:27:47 GMT-0400 (EDT)
    0 secs (0 hrs) behind the primary
source: m2.example.net:27017
    syncedTo: Tue Apr 10 2018 10:27:43 GMT-0400 (EDT)
    0 secs (0 hrs) behind the primary
source: m3.example.net:27017
    syncedTo: Tue Apr 10 2018 10:27:39 GMT-0400 (EDT)
    0 secs (0 hrs) behind the primary

13.4.6 Oplog 크기 변경

  • 프라이머리의 oplog는 유지 보수 시간, 잘못된 부분을 고칠 수 있는 시간
  • 일반적으로 1주 정도 데이터를 보유할 수 있는 oplog 가 바람직
  • 일반적으로 oplog의 크기는 줄이면 안됨

1.복제 셋 멤버에 연결

2.oplog 의 현재 크기를 확인

> use local
> db.oplog.rs.stats(1024*1024).maxSize	//메가바이트로 표시

3.복제 셋 멤버의 oplog 크기 변경

> db.adminCommand({replSetResizeOplog: 1, size: 16000})	//16기가

13.4.7 인덱스 구축하기

  • 프라이머리에 인덱스 구축 전송하면, 세컨더리는 build index 연산을 복제할 때 인덱스를 구축
  • 인덱스 구축은 멤버를 이용 불가능한 상태로 만들 수 있는 리소스 집약적 연산
  • unique 인덱스 만들 때는 컬렉션에 모든 쓰기를 중지해야함. 복제 셋 멤버끼리 데이터 불일치 가능성
  • 애플리케이션에 대한 영향을 최소화하려면 인덱스는 한 멤버씩 구축
  • unique 인덱스 만들 때는 프라이머리에 먼저 구축

세컨더리 인덱스 구축

1. 세컨더리 종료

2. 종료한 세컨더리 독립 실행형 서버로 재시작

3. 재시작한 서버에 인덱스 구축

4. 서버를 복제 셋 멤버로 재시작

5. 복제 셋의 각 세컨더리에 1~4단계 반복

 

프라이머리 인덱스 구축

1. 프라이머리에 인덱스 구축. 트래픽이 적을 때 'off' 시간에 진행

읽기 선호도 수정하여 세컨더리로 부하를 보내도록 경로 변경

2. 프라이머리를 강등한 후 세컨더리 인덱스 구축 2~4단계 진행

인덱스 구축이 완료된 후 기존 프라이머리를 복제 셋에 재도입

13.4.8 한정된 예산에서 복제하기

  • 성능 좋은 서버는 프라이머리로 쓰고,
  • 상대적으로 값싼 서버는 재해 복구용 세컨더리 서버로 트래픽을 처리하지 않게 한다
  • priority : 0 해당 서버가 절대 프라이머리가 되지 않도록 설정
  • hidden : true 클라이언트가 해당 세컨더리에 읽기 요청을 절대 보내지 않도록 설정
  • buildIndexes : false 처리해야하는 부하를 줄여줌
  • votes : 0 해당 서버가 다운되더라도 기존 프라이머리가 유지되도록 해줌

 

728x90
반응형

'DB > MongoDB' 카테고리의 다른 글

[MongoDB] 샤딩 구성  (0) 2023.12.10
[MongoDB] 샤딩  (0) 2023.08.30
[MongoDB] 애플리케이션에서 복제 셋 연결  (0) 2023.08.01
[MongoDB] 복제 셋 구성 요소  (0) 2023.07.27
[MongoDB] 복제 셋 설정  (0) 2023.07.11
반응형
300x250