복제 세트에서 읽기 성능 최적화를 위한 모범 사례
읽기 설정, 읽기 고려 사항, 지연 모니터링, 인덱싱 및 타임아웃 제어를 통해 MongoDB 복제 세트 읽기 성능을 개선합니다.
복제 세트에서 읽기 성능 최적화를 위한 모범 사례
MongoDB 복제 세트는 고가용성을 제공하지만 자동으로 읽기 속도를 빠르게 하지는 않습니다. 애플리케이션이 모든 쿼리를 프라이머리로 보내거나, 약한 인덱스를 사용하거나, 지연된 세컨더리에서 읽는다면 사용자는 느린 페이지와 오래된 데이터를 경험하게 됩니다.
좋은 읽기 성능은 올바른 읽기 설정 선택, 필요한 일관성 수준에 맞는 읽기 고려 사항 설정, 복제 지연 모니터링, 그리고 느린 쿼리를 먼저 수정하는 것에서 비롯됩니다.
복제 세트에서 읽기 경로 이해하기
표준 복제 세트 배포에서 하나의 멤버는 프라이머리로 지정되어 모든 쓰기를 처리합니다. 나머지 멤버는 세컨더리로, 프라이머리에서 데이터를 비동기적으로 복제합니다. 애플리케이션 읽기는 구성에 따라 프라이머리로 전송되거나 세컨더리에 분산될 수 있습니다.
읽기 최적화는 즉각적인 데이터 일관성(종종 프라이머리에서 읽어야 함)의 필요성과 프라이머리에서 트래픽을 분산(세컨더리에서 읽음)하려는 요구 사이의 균형을 맞추는 것을 의미합니다.
1. 읽기 고려 사항의 전략적 사용
읽기 고려 사항은 읽기 작업에 필요한 데이터 일관성의 정도를 정의합니다. 완화된 수준으로 충분할 때 지나치게 엄격한 읽기 고려 사항을 설정하면 여러 노드의 확인을 기다려야 하므로 읽기 지연의 일반적인 원인이 됩니다.
사용 가능한 읽기 고려 사항
MongoDB는 여러 읽기 고려 사항을 제공하며, 각각 지연 시간과 내구성/일관성을 절충합니다:
| 읽기 고려 사항 | 설명 | 사용 사례 |
|---|---|---|
majority |
투표 노드의 과반수가 커밋한 것으로 확인된 데이터를 반환합니다. 표준 기본값. | 높은 내구성이 필요한 일반 목적 읽기. |
local |
쓰기 확인과 관계없이 읽는 멤버에서 사용 가능한 최신 데이터를 반환합니다. | 약간의 오래된 데이터를 허용할 수 있는 읽기(예: 대시보드 카운터). |
linearizable |
프라이머리에서 읽으며 읽기 시작 전에 확인된 모든 쓰기를 반영합니다. readConcern: "linearizable" 및 관련 쓰기에 대한 과반수 쓰기 고려 사항이 필요합니다. |
잠금 소유권 확인과 같이 최신 확인 상태를 관찰해야 하는 드문 읽기. |
최적화 팁: local 또는 majority 기본값 사용
중요하지 않은 읽기(예: 자주 업데이트되지 않는 구성 데이터 또는 캐시된 결과 로드)의 경우 세컨더리에서 local 읽기 고려 사항을 사용하세요. 이렇게 하면 동기화 지연을 피할 수 있습니다.
예제: 세션 수준에서 읽기 고려 사항 설정
// 이 특정 세션에 대해 읽기 고려 사항을 'local'로 설정
const session = mongoClient.startSession({ readConcern: { level: "local" } });
// 세션을 사용하여 찾기 작업 수행
db.collection('mydata').find().session(session).toArray();
경고: 세컨더리에서
local고려 사항으로 읽으면 프라이머리 기준으로 오래된 데이터를 반환할 수 있습니다.
2. 세컨더리로 읽기 분산
기본적으로 MongoDB는 읽기를 프라이머리로 전송합니다. 읽기 용량을 확장하려면 읽기 설정을 사용하여 명시적으로 읽기를 세컨더리로 전송해야 합니다.
읽기 설정 이해
읽기 설정은 복제 세트의 어떤 멤버가 읽기 요청을 처리할 자격이 있는지와 선택 순서를 결정합니다.
일반적인 읽기 설정은 다음과 같습니다:
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. 세컨더리 동기화 및 지연 관리
세컨더리로 읽기를 라우팅하는 경우 해당 읽기의 성능은 전적으로 세컨더리가 프라이머리를 얼마나 빠르게 따라잡고 있는지에 달려 있습니다. 높은 복제 지연은 세컨더리가 오래된 데이터를 제공하거나 지연이 너무 크면 읽기가 실패하거나 시간 초과될 수 있음을 의미합니다.
복제 지연 모니터링
항상 프라이머리와 세컨더리 간의 optime 차이를 모니터링하세요. rs.status()는 멤버별 복제 상태를 보여주며, MongoDB Atlas, Cloud Manager 또는 Ops Manager와 같은 관리 도구는 지연에 대해 경고할 수 있습니다.
rs.status().members.map(m => ({
name: m.name,
stateStr: m.stateStr,
optimeDate: m.optimeDate
}))
쓰기 고려 사항이 세컨더리 성능에 미치는 영향
이 문서는 읽기에 초점을 맞추고 있지만, 높은 쓰기 고려 사항 설정은 프라이머리를 느리게 하여 간접적으로 읽기 성능에 영향을 미칠 수 있으며, 이로 인해 세컨더리가 더 뒤처지게 됩니다.
예를 들어, w: "majority"를 요구하면 클라이언트는 쓰기가 투표 데이터 보유 멤버의 과반수에 도달할 때까지 확인을 받지 못합니다. 디스크나 네트워크 압력으로 인해 세컨더리가 느린 경우 애플리케이션 쓰기 지연 시간이 증가할 수 있으며, 동일한 과부하된 세컨더리가 느린 읽기를 제공할 수도 있습니다.
쓰기 고려 사항에 대한 모범 사례(간접적인 읽기 최적화): 읽기를 더 빠르게 보이게 하기 위해 쓰기 고려 사항을 낮추지 마세요. 내구성 요구 사항에 따라 쓰기 고려 사항을 선택한 다음 지연의 원인(느린 디스크, 과부하된 세컨더리, 작은 oplog, 네트워크 문제 또는 복제와 경쟁하는 쿼리)을 수정하세요.
4. 인덱싱 및 쿼리 최적화
어떤 구성 설정도 잘못 작성된 쿼리를 극복할 수 없습니다. 빠른 읽기의 기본 원칙은 강력한 인덱싱입니다.
주요 인덱싱 고려 사항
- 커버드 쿼리: 디스크에서 문서를 가져오지 않고 인덱스로 완전히 충족될 수 있는 쿼리를 설계하세요. 이것이 가능한 가장 빠른 읽기입니다.
- 인덱스 정렬: 인덱스가
find(),sort()및projection()절에 사용된 필드와 일치하는지 확인하세요. - 컬렉션 스캔 방지: 쿼리 프로파일러에서 읽기 작업이 전체 컬렉션 스캔(
COLLSCAN) 대신 인덱스(IXSCAN)를 사용하는지 항상 확인하세요.
쿼리 타임아웃 조정
애플리케이션이 심하게 지연된 세컨더리에 도달하면 쿼리가 시간 초과될 수 있습니다. 애플리케이션에서 합리적인 타임아웃을 구성하여 일시적인 지연을 적절히 처리하고, 무기한 대기하는 대신 프라이머리로 대체하거나 나중에 다시 시도하세요.
읽기 최적화 단계 요약
MongoDB 복제 세트에서 최적의 읽기 성능을 달성하려면 다음 실행 가능한 단계를 따르세요:
- 읽기 유형 식별: 최신 프라이머리 데이터가 필요한 읽기와 세컨더리에서 최종 일관성을 허용할 수 있는 읽기를 분류하세요.
- 읽기 설정 구성: 대부분의 애플리케이션 트래픽에 대해
secondaryPreferred또는nearest를 사용하도록 연결 문자열 또는 세션 옵션을 설정하세요. - 지연 모니터링:
rs.status(), 드라이버 메트릭 또는 모니터링 플랫폼에서 복제 지연을 지속적으로 모니터링하세요. 지연이 지속적으로 높으면 세컨더리 하드웨어 또는 네트워킹 문제를 조사하세요. - 쓰기 고려 사항 검토: 쓰기 고려 사항이 프라이머리를 과도하게 느리게 하지 않는지 확인하세요. 이는 세컨더리에 최신 데이터를 공급하지 못하게 합니다.
- 철저한 인덱싱: 자주 실행되는 모든 읽기 경로가 효율적인 인덱스를 사용하는지 확인하세요.
복제 세트 읽기 확장은 데이터의 오래됨에 대해 정직할 때 가장 잘 작동합니다. 사용자에게 중요한 읽기는 최신 상태여야 할 때 프라이머리로 보내고, 분석이나 대시보드와 같이 지연을 허용할 수 있는 읽기에는 세컨더리를 사용하며, 트래픽이 변함에 따라 쿼리 계획과 복제 상태를 지속적으로 측정하세요.