레플리카 세트에서 읽기 성능 최적화를 위한 모범 사례
MongoDB 레플리카 세트는 프로덕션 환경에서 고가용성과 데이터 중복성을 보장하는 데 필수적입니다. 장애 조치 및 내구성이 주요 이점이지만, 잘못 구성된 레플리카 세트는 상당한 읽기 지연 시간을 유발하여 빠른 데이터 검색에 의존하는 애플리케이션의 속도를 저하시킬 수 있습니다. 읽기 성능을 최적화하려면 데이터 복제 방식, 멤버 간 읽기 분산 방식, 그리고 애플리케이션이 실제로 요구하는 일관성 보장 수준을 신중하게 조정해야 합니다.
이 가이드는 MongoDB 레플리카 세트에서 쿼리 속도에 직접적인 영향을 미치는 읽기 고려 사항(read concerns), 쓰기 고려 사항(write concerns), 동기화 메커니즘을 포함한 중요한 구성 설정을 탐구합니다. 이러한 모범 사례를 구현하면 분산 클러스터 전반에서 쿼리 처리량을 최대화하고 지연 시간을 최소화할 수 있습니다.
레플리카 세트의 읽기 경로 이해
표준 레플리카 세트 배포에서 한 멤버는 프라이머리(primary)로 지정되어 모든 쓰기 작업을 처리합니다. 나머지 멤버들은 세컨더리(secondaries)로서 프라이머리로부터 데이터를 비동기적으로 복제합니다. 애플리케이션 읽기는 구성에 따라 프라이머리로 지정되거나 세컨더리에 분산될 수 있습니다.
읽기 최적화는 즉각적인 데이터 일관성 요구 사항(종종 프라이머리에서 읽기를 요구함)과 프라이머리의 부하를 덜어주고자 하는 목표(세컨더리에서 읽기 수행) 사이의 균형을 맞추는 것을 의미합니다.
1. 읽기 고려 사항의 전략적 사용
읽기 고려 사항(Read Concern)은 읽기 작업에 필요한 데이터 일관성의 정도를 정의합니다. 완화된 수준으로 충분한 상황에서 지나치게 엄격한 읽기 고려 사항을 설정하는 것은 읽기 지연 시간의 일반적인 원인입니다. 이는 여러 노드로부터의 확인을 기다리도록 작업을 강제할 수 있기 때문입니다.
사용 가능한 읽기 고려 사항
MongoDB는 지연 시간과 내구성/일관성 간에 균형을 이루는 여러 읽기 고려 사항을 제공합니다:
| 읽기 고려 사항 | 설명 | 사용 사례 |
|---|---|---|
strong |
다수 투표 노드에서 내구성이 보장된 데이터를 반환합니다. 가장 높은 일관성. | 데이터 손실을 용납할 수 없는 중요 트랜잭션. |
majority |
투표 노드 다수로부터 커밋이 승인된 데이터를 반환합니다. 표준 기본값. | 높은 내구성이 요구되는 일반적인 읽기. |
local |
읽기 작업이 수행되는 멤버에서 사용 가능한 최신 데이터를 반환하며, 쓰기 확인 여부는 무시합니다. | 약간의 오래된 데이터를 허용할 수 있는 읽기(예: 대시보드 카운터). |
linearizable |
읽기 작업이 시작되기 전에 성공적으로 완료된 모든 이전 쓰기 작업의 결과를 반영함을 보장합니다. (다수 쓰기 고려 사항 필요). 매우 높은 조정 지연 시간. | 최신 쓰기 결과를 즉시 확인해야 하는 읽기. |
최적화 팁: local 또는 majority를 기본값으로 사용
중요하지 않은 읽기(예: 자주 업데이트되지 않는 구성 데이터 또는 캐시된 결과 로드)의 경우, 세컨더리에서 local 읽기 고려 사항을 사용하십시오. 이렇게 하면 동기화 지연을 방지할 수 있습니다.
예시: 세션 수준에서 읽기 고려 사항 설정
// 이 특정 세션에 대해 읽기 고려 사항을 'local'로 설정
const session = mongoClient.startSession({ readConcern: { level: "local" } });
// 세션을 사용하여 find 작업 수행
db.collection('mydata').find().session(session).toArray();
경고: 세컨더리에서
local고려 사항으로 읽으면 아직 복제되지 않은 데이터를 읽게 되어 오래된 결과를 초래할 수 있습니다.
2. 세컨더리에 읽기 분산
기본적으로 MongoDB는 읽기를 프라이머리로 보냅니다. 읽기 용량을 확장하려면 읽기 우선순위(Read Preference) 설정을 사용하여 세컨더리로 읽기를 명시적으로 지정해야 합니다.
읽기 우선순위 이해
읽기 우선순위는 레플리카 세트의 어떤 멤버가 읽기 요청을 만족시키는 데 적합한지, 그리고 어떤 순서로 선택되어야 하는지를 결정합니다.
일반적인 읽기 우선순위는 다음과 같습니다.
primary: (기본값) 프라이머리만 적합합니다.primaryPreferred: 먼저 프라이머리를 시도하고, 프라이머리를 사용할 수 없으면 세컨더리로 폴백합니다.secondary: 세컨더리만 적합합니다. 사용 가능한 세컨더리가 없으면 작업이 실패합니다.secondaryPreferred: 세컨더리를 선호하며, 사용 가능한 세컨더리가 없으면 프라이머리로 폴백합니다.nearest: 클라이언트와의 네트워크 지연 시간이 가장 짧은 멤버(프라이머리 또는 세컨더리)를 선택합니다.
최적화 팁: secondaryPreferred 또는 nearest 사용
대부분의 읽기 집약적 애플리케이션의 경우, secondaryPreferred를 사용하면 사용 가능한 모든 세컨더리에 쿼리 부하를 분산하여 프라이머리의 부하를 크게 줄일 수 있습니다.
지리적으로 분산된 애플리케이션 서버가 있는 경우, 때때로 프라이머리에 액세스하더라도 클라이언트의 네트워크 지연 시간을 최소화하는 nearest가 종종 최선의 선택입니다.
예시: secondaryPreferred로 연결하기
애플리케이션 드라이버로 연결할 때 읽기 우선순위를 지정합니다.
const uri = "mongodb://host1,host2,host3/?replicaSet=rs0&readPreference=secondaryPreferred";
// 또는 드라이버 설정에서 연결 옵션 사용
const options = {
readPreference: "secondaryPreferred"
};
3. 세컨더리 동기화 및 지연 관리
세컨더리로 읽기를 라우팅하는 경우, 해당 읽기의 성능은 세컨더리가 프라이머리를 얼마나 빨리 따라잡고 있는지에 전적으로 달려 있습니다. 높은 복제 지연(replication lag)은 세컨더리가 오래된 데이터를 제공하고 있음을 의미하거나, 지연이 너무 높으면 읽기가 실패하거나 시간 초과될 수 있습니다.
복제 지연 모니터링
항상 프라이머리와 세컨더리 간의 optimeDate 차이를 모니터링해야 합니다. rs.printReplicationInfo() 또는 모니터링 시스템(예: MongoDB Cloud Manager/Ops Manager)과 같은 도구가 필수적입니다.
// 세컨더리 멤버에서 실행
rs.printReplicationInfo()
// 보고된 지연 시간 확인
// 'secsBehindPrimary' 필드를 확인하십시오.
쓰기 고려 사항이 세컨더리 성능에 미치는 영향
이 문서는 읽기에 중점을 두지만, 높은 쓰기 고려 사항 설정은 프라이머리의 속도를 늦추고, 이는 다시 세컨더리가 최신 데이터를 따라가지 못하게 하여 간접적으로 읽기 성능에 영향을 미칠 수 있습니다.
예를 들어, w: 'majority' 쓰기 확인을 요구하면 프라이머리가 대다수의 노드가 쓰기를 승인할 때까지 기다려야 작업을 진행할 수 있습니다. 승인이 느리면(네트워크 포화 또는 과부하된 세컨더리 때문) 전체 복제 파이프라인이 느려집니다.
쓰기 고려 사항에 대한 모범 사례(간접적인 읽기 최적화): 쓰기 고려 사항이 적절하게 설정되어 있는지 확인하십시오. 세컨더리가 많은 경우, 더 낮은 w: 값(예: w: majority 대신 w: 2)을 사용하면 프라이머리가 쓰기를 더 빨리 적용하도록 도와 세컨더리가 최신 상태를 유지하도록 할 수 있습니다.
4. 인덱싱 및 쿼리 최적화
어떤 구성 설정도 잘못 작성된 쿼리를 만회할 수는 없습니다. 빠른 읽기의 근본 원칙은 강력한 인덱싱이라는 점은 변함이 없습니다.
주요 인덱싱 고려 사항
- 커버드 쿼리(Covered Queries): 인덱스만으로 쿼리를 완전히 만족시켜 디스크에서 문서를 가져올 필요가 없도록 쿼리를 설계합니다. 이는 가능한 가장 빠른 읽기입니다.
- 인덱스 정렬:
find(),sort(),projection()절에 사용된 필드와 인덱스가 일치하는지 확인합니다. - 컬렉션 스캔 방지: 읽기 작업이 전체 컬렉션 스캔(
COLLSCAN)을 수행하는 대신 인덱스(IXSCAN)를 사용하고 있는지 쿼리 프로파일러에서 항상 확인합니다.
쿼리 시간 초과 튜닝
애플리케이션이 심하게 지연되는 세컨더리에 액세스하는 경우 쿼리가 시간 초과될 수 있습니다. 일시적인 지연을 우아하게 처리하고 무한정 중단되는 대신 프라이머리로 폴백하거나 나중에 재시도할 수 있도록 애플리케이션에서 합리적인 시간 초과를 구성하십시오.
읽기 최적화 단계 요약
MongoDB 레플리카 세트에서 최적의 읽기 성능을 달성하려면 다음 실행 가능한 단계를 따르십시오.
- 읽기 유형 식별: 읽기를 두 그룹으로 분류합니다. 강력한 일관성이 필요한 읽기(프라이머리/강력한 읽기 고려 사항 사용)와 최종적 일관성을 허용하는 읽기(세컨더리/로컬 읽기 고려 사항 사용).
- 읽기 우선순위 구성: 대부분의 애플리케이션 트래픽에 대해 연결 문자열 또는 세션 옵션을
secondaryPreferred또는nearest를 사용하도록 설정합니다. - 지연 모니터링: 복제 지연(
secsBehindPrimary)을 지속적으로 모니터링합니다. 지연이 지속적으로 높으면 세컨더리 하드웨어 또는 네트워킹 문제를 조사해야 합니다. - 쓰기 고려 사항 검토: 쓰기 고려 사항이 프라이머리의 속도를 부당하게 늦추어 세컨더리가 최신 데이터를 받지 못하게 하지 않도록 확인합니다.
- 철저한 인덱싱: 빈번하게 실행되는 모든 읽기 경로가 효율적인 인덱스로 커버되는지 확인합니다.