-
[MongoDB] 재해복구 시스템을 위한 몽고디비 노드 설정.Software Development/Database 2023. 3. 10. 20:30
재해복구 시스템을 위해서는 다른 Zone 또는 Region에 클러스터를 배포해야 한다.
예를 들어, 데이터센터 A와 데이터센터 B가 있을 경우, A, B에 각각 2~3대의 노드를 배포하는 방식으로 동작한다.
몽고디비는 프라이머리 노드 선출을 위해 노드의 개수를 홀수로 설정하는 것을 권장한다.
만약 A, B에 2대 2대가 있다면, 4대의 노드로 짝수의 노드이기 때문에 해당 권장사항을 따르지 않는다.
이를 해결하기 위해서, A에 3대 B에 2대를 설정하여 홀수개의 노드로 해당 권장사항을 충족할 수 있다.
그런데 위의 방식은 문제점이 존재한다.
만약 A 데이터센터가 정전, 네트워크 이슈 같은 이유로 3대가 사용이 불가능하게 된다면 어떻게 될까?
5대의 노드 중에 총 B 데이터 센터의 2대의 노드만 살아있게 된다.
몽고디비는 과반의 노드가 살아있어야 정상 작동한다.
이렇게 될 경우, B 데이터 센터에 노드 2대를 추가한 의미가 사라지게 된다.
이를 해결하기 위해서 C 데이터 센터에 2개의 노드를 추가하여 A, B, C 각각 2개의 모두를 가지도록 설정하게 된다면 총 6개로 A, B, C 데이터센터 중에 하나가 불능의 상태라도 몽고디비 클러스터를 유지할 수 있다.
그런데 비용의 관점에서 생각해본다면, 2대의 노드가 필요한 시스템에 재해복구 시스템을 위해서 4대의 노드가 추가했다. 재해복구를 위해서 이 비용을 쓰는게 타당해 보일 수 있지만, 비용의 관점에서 최적인지 고민할 필요가 있다.
몽고디비는 클러스터 구성을 위해 PSA라는 방식이 존재한다(P: 프라이머리, S: 세컨더리, A: 아비터).
아비터 노드(중재자 노드)는 데이터를 보유한 노드가 아니다. 이 노드는 투표권만 있으며, 기존 프라이머리 불능시에 프라이머리 선출을 위한 투표에 참여한다. 그렇기 때문에 해당 노드에는 데이터도 없으며, 많은 리소스를 필요로 하지 않는다.
그렇다면, A, B 데이터 센터에 각각 2개의 데이터 보유 노드를 구성하고 C 데이터 센터 또는 클라우드 서비스를 사용하여, 적은 비용이 드는 아비터 노드 한대만 추가하면 홀수개의 노드를 구성할 수 있다.
만약 A 데이터 센터가 불능이 되더라도 2개의 노드만 죽고 3개의 노드를 살아있다. 과반의 노드가 살아있기 때문에 정상적으로 운영될 수 있다.
그러나, 현실은 달랐다. 아비터 노드를 포함한 과반의 노드가 살아있다고 정상 운영되는지 테스트를 진행해보았다.
분명 클러스터는 살아있지만 성능이 엄청나게 느려지는 현상이 발생했다. 성능이 느리다면, 운영에 적용할 수 없다.
PSA 방식으로 클러스터를 구축하여 비용 절감에 대한 기대를 했지만, 사용할 수 없는 것이다. 무엇이 문제일까?
몽고디비 jira에 비슷한 현상을 겪는 사용자가 이슈를 등록했었다[1].
https://jira.mongodb.org/browse/SERVER-36877
핵심은 위 링크의 아래 문장에 있다.
When your replica set is not able to satisfy the read concern, your primary is required to store oplog data in the cache, which can result in the sort of resource utilization you're see ...
리플리카셋이 read concern을 만족할 수 없다면, 프라이머리 노드가 oplog 데이터를 캐시에 저장하면서 성능 저하가 발생하게 된다.
해결책으로 아비터 노드를 데이터 보유 노드로 변경해라고 한다.
이렇게 바꿔라는 이유는 read concern은 기본값으로 majority를 사용한다. 즉, 과반의 데이터 보유 노드가 살아있어야 oplog를 캐시에 저장하지 않는 것이다.
아비터 노드를 데이터 보유 노드로 변경하면, PSA 구성이 아니며 A, B, C 데이터 센터에 각각 2, 2, 1개의 데이터 보유 노드를 설정하면 되는 것이다.
해당 방식이 가장 심플하고 명확한 해결책이다. 그러나, 누구에게나 사정이라는 것이 있고 데이터센터 3개에 노드를 구성하는게 부담스러울 수 있다.
그렇다면, 다른 방법으로 다음과 같은 해결책을 생각할 수 있다.
read concern을 majority가 아니도록 수정하면 가능하지 않을까?
물론 설정이 가능하다[2]. 그러나 데이터 일관성의 관점에서 해당 방식은 안전하지 못하다.
더 좋은 방법은 없을까?
찾아보니 PSA 방식에서 성능 이슈에 대한 내용이 몽고디비 문서에서 다뤄지고 있었다[3].
제시하는 해결 방법으로는 rs.conf를 수정하는 것이다.
cfg = rs.conf(); cfg["members"][<array_index>]["votes"] = 0; cfg["members"][<array_index>]["priority"] = 0; rs.reconfig(cfg);
즉, 사용할 수 없거나, lagging이 발생하는 노드에 대해서 priority와 votes를 0으로 설정하는 것이다.
꽤 괜찮은 방법으로 보인다. 제시하는 방식의 핵심 내용은 아래와 같다.
Setting the configuration of the node to votes: 0 reduces the number of nodes required to commit a write with write concern "majority" from two to one and allows these writes to succeed.[3]
테스트를 진행해본 결과 정상작동하지 않았다. 원인을 조금 더 찾아봐야겠지만 말이다.
핵심은 데이터 보유 노드의 과반을 유지하는 것인데, 위의 방법이 정상 동작하지 않는다면 다른 방법으로는 어떤게 있을까?
적용할 수 있는 방법으로 사용할 수 없거나, lagging이 발생하는 노드를 replica-set에서 제외시키는 것이다.
예를 들어, A 데이터 센터가 불능이라면 rs.remove로 해당 데이터센터의 데이터 보유 노드 중 하나를 제외시키면 리플리카셋의 과반이 유지될 수 있다.
각 데이터센터에 노드가 2개, 3개, 5개에 등 노드의 수와 관계없이 불능인 데이터센터의 노드 하나만 제외하면 과반의 수를 달성할 수 있을 것이다.
위의 방법은 하나의 프라이머리를 가진 하나의 클러스터를 가지고 데이터센터 장애에 대응하기 위한 방법이다.
다른 방법으로는 멀티 클러스터로 구축하여 두 클러스터간의 싱크를 맞춰서 데이터센터 장애에 대응하는 방법도 있다. 몽고디비에서 mongosync라는 유틸리티가 있다[4].
해당 방식은 최소 몽고디비 6.0.4 버전 이상을 설치해야 가능하다.
해당 방식은 몇가지 제한이 있지만[5], 재해복구를 위한 방법[6]으로 mongosync를 사용하는 만큼 믿을 수 있는 방법이라 생각된다.
해당방식은 원본 클러스터와 대체 클러스터가 계속해서 싱크를 맞추는 방식으로 진행되는데, 대체 클러스터를 원본 클러스터로 변경하려면 몇가지 절차가 필요하다.
해당 절차는 수동으로 진행해야 하는데, 이 부분에서 서비스 불능 상태가 될 수 있다.
[1] https://jira.mongodb.org/browse/SERVER-36877
[3] https://www.mongodb.com/docs/manual/tutorial/mitigate-psa-performance-issues/
[4] https://www.mongodb.com/docs/cluster-to-cluster-sync/current/#std-label-c2c-index
[6] https://www.mongodb.com/docs/cluster-to-cluster-sync/current/reference/disaster-recovery/
'Software Development > Database' 카테고리의 다른 글
[MongoDB] createIndex commitQuorum (0) 2023.03.31 [MongoDB] 몽고디비 설치시 최적의 하드웨어 및 OS 설정 (0) 2023.03.12 [MongoDB] Compound Index 생성해도 왜 쿼리가 느리지? (0) 2022.05.31 데이터베이스 인터널스 (0) 2022.04.27 [MongoDB] collection.count(), collection.countDocuments({}) (0) 2022.01.14