일반적인 MongoDB 복제 지연 문제 진단 및 해결
이 포괄적인 가이드를 통해 MongoDB 복제 지연의 복잡성을 탐색하세요. 복제 세트에서 데이터 일관성과 고가용성을 저해하는 일반적인 문제를 식별, 진단 및 해결하는 방법을 배웁니다. 이 문서는 oplog 이해 및 `rs.status()`로 지연 감지부터 oplog 크기 부족, 네트워크 병목, 리소스 제약, 누락된 인덱스에 대한 실용적인 솔루션까지 모든 것을 다룹니다. 건강하고 성능이 뛰어나며 탄력적인 MongoDB 환경을 유지하기 위한 실행 가능한 전략과 모범 사례를 갖추세요.
일반적인 MongoDB 복제 지연 문제 진단 및 해결
MongoDB 복제 지연은 단순히 대시보드의 숫자가 아닙니다. 애플리케이션의 동작 방식을 변화시킵니다. 사용자가 프로필을 업데이트하고, 다른 요청이 보조 노드에서 읽기를 수행하면 이전 값이 반환됩니다. 노드가 실패하지만 최상의 보조 노드가 여전히 뒤처져 있어 장애 조치가 예상보다 오래 걸립니다. 보고 쿼리가 잘못된 멤버에 도달하면 복제 세트가 하나의 보조 노드가 계속해서 프라이머리에서 멀어지는 것을 제외하고는 정상으로 보입니다.
복제 지연에 대해 생각하는 유용한 방법은 간단합니다: 프라이머리가 oplog 항목을 생성하는 속도가 하나 이상의 보조 노드가 가져와서 적용하는 속도보다 빠른 것입니다. 해결 방법은 사용자 환경에서 이 문장의 어느 쪽이 사실인지에 따라 달라집니다. 때로는 프라이머리가 버스트로 너무 많이 쓰고 있습니다. 때로는 보조 노드의 성능이 부족합니다. 때로는 네트워크가 느립니다. 때로는 secondaryDelaySecs로 구성되어 있어 지연이 의도적입니다. 첫 번째 작업은 변경을 가하기 전에 이러한 경우를 분리하는 것입니다.
지연의 실제 형태부터 확인하세요
oplog 크기를 조정하거나 mongod를 다시 시작하는 것으로 시작하지 마십시오. 먼저 지연이 꾸준한지, 간헐적인지, 하나의 멤버에 국한되었는지, 아니면 모든 보조 노드에 영향을 미치는지 확인하십시오.
mongosh에서 다음으로 시작하십시오:
rs.status()
각 멤버의 stateStr, optimeDate, lastHeartbeatMessage 및 health 필드를 확인하십시오. 하나의 보조 노드가 뒤처져 있고 다른 노드가 최신 상태라면, 디스크, CPU, 로컬 읽기, 로컬 유지 관리 또는 잘못된 네트워크 경로와 같은 멤버별 문제가 있을 가능성이 높습니다. 모든 보조 노드가 뒤처져 있다면, 프라이머리 쓰기 볼륨, 프라이머리에서 나가는 네트워크 처리량 또는 비정상적으로 큰 작업을 더 자세히 살펴보십시오.
빠른 oplog 윈도우 확인을 위해 다음을 실행하십시오:
rs.printReplicationInfo()
oplog 윈도우는 현재 oplog가 포함하는 시간을 알려줍니다. 복제가 정상이라는 것을 의미하지는 않습니다. 보조 노드가 초기 동기화가 필요할 위험에 처하기 전에 얼마나 뒤로 갈 수 있는지를 나타냅니다. oplog 윈도우가 6시간이고 유지 관리 창이 일반적으로 8시간인 경우, 현재 지연이 0이더라도 실제 운영 위험이 있습니다.
보조 노드의 경우 다음도 유용합니다:
rs.printSecondaryReplicationInfo()
오래된 예제에서는 rs.printSlaveReplicationInfo()를 볼 수 있습니다. 최신 용어는 "secondary"를 사용하지만, 오래된 셸 도우미와 블로그 게시물은 여전히 "slave"를 사용할 수 있습니다. 필드는 이름보다 더 중요합니다.
라이브 셸에서 작은 스크립트를 원한다면, 프라이머리 optime을 각 보조 노드와 비교하십시오:
const status = rs.status();
const primary = status.members.find(m => m.stateStr === "PRIMARY");
status.members
.filter(m => m.stateStr === "SECONDARY")
.forEach(m => {
const lagSeconds = (primary.optimeDate - m.optimeDate) / 1000;
print(`${m.name}: ${lagSeconds}s behind primary`);
});
이것을 스냅샷으로 취급하고 진단으로 간주하지 마십시오. 일괄 가져오기 중에 20초 뒤처진 보조 노드는 빠르게 따라잡으면 괜찮을 수 있습니다. 정상 트래픽 중에 항상 20초 뒤처진 보조 노드는 주의가 필요합니다.
지연이 의도적인지 확인하십시오
잘못된 인시던트를 쫓기 전에 복제 세트 구성을 검사하십시오:
rs.conf()
지연된 멤버는 설계상 프라이머리보다 뒤처지도록 구성됩니다. 최신 MongoDB 구성에서는 멤버에서 secondaryDelaySecs를 찾으십시오. 이 멤버는 짧은 기간 동안 데이터의 이전 보기를 보존할 수 있기 때문에 일부 복구 시나리오에 유용합니다. 신선한 읽기에 사용되어서는 안 되며, 예상 지연은 일반 지연 알림에서 제외되어야 합니다.
실제 운영에서 제가 보는 실수는 모든 지연된 멤버를 마치 고장난 것처럼 알림을 보내는 것입니다. 구성된 지연을 초과하는 지연에 대해서만 알림을 보내십시오. 멤버가 1시간 지연되고 1시간 5분의 지연을 보인다면, 실제 지연은 약 5분입니다.
oplog 윈도우가 너무 작은 경우
oplog는 local 데이터베이스의 고정 크기 컬렉션입니다. 보조 노드는 이를 읽고 순서대로 작업을 적용합니다. 보조 노드가 너무 뒤처져서 프라이머리가 더 이상 필요한 oplog 항목을 가지고 있지 않으면, 일반적인 따라잡기가 더 이상 불가능합니다. 멤버는 일반적으로 초기 동기화 또는 적절한 백업에서 복원이 필요합니다.
이것이 oplog 윈도우가 중요한 이유입니다. 예상 다운타임, 유지 관리, 네트워크 중단 및 최대 쓰기 버스트보다 더 많은 시간을 포함해야 합니다. 보편적인 "올바른" oplog 크기는 없습니다. 조용한 클러스터는 작은 oplog에서 며칠의 기록을 유지할 수 있습니다. 업데이트가 많은 바쁜 클러스터는 같은 크기를 짧은 시간에 소진할 수 있습니다.
oplog 윈도우가 피크 트래픽 중에 줄어들고 있다면, 다음 유지 관리 창 전에 늘리십시오. 지원되는 MongoDB 버전에서는 replSetResizeOplog를 사용하여 local.oplog.rs를 삭제하고 다시 만드는 대신 사용하십시오. 복제 세트 멤버에서 oplog를 삭제하는 것은 고위험 복구 작업이지 일반적인 튜닝 단계가 아닙니다.
oplog 크기를 조정하려는 멤버에서 크기 조정 명령을 실행하십시오:
use admin
db.adminCommand({ replSetResizeOplog: 1, size: 10240 })
size 값은 메가바이트 단위입니다. 10240 값은 약 10GB를 의미합니다. 필요에 따라 각 멤버의 크기를 조정하십시오. MongoDB Atlas와 같은 관리형 환경에서는 직접적인 파일 시스템 또는 프로세스 제어를 가정하는 대신 플랫폼에서 지원하는 구성 경로를 사용하십시오.
크기 조정 후 실제 쓰기 부하에서 새 윈도우를 확인하십시오. 더 큰 oplog는 oplog에서 떨어질 가능성을 줄이지만, 느린 보조 노드가 작업을 더 빨리 적용하게 하지는 않습니다.
하나의 보조 노드가 느린 경우
하나의 보조 노드만 지연된다면, 해당 호스트에 로그인하여 일반적인 시스템 증상을 확인하십시오. MongoDB는 종종 실제로 디스크 포화 상태인데 비난을 받습니다.
다음과 같은 도구를 사용하십시오:
iostat -xz 1
vmstat 1
top
mongostat --host secondary.example.com:27017
mongotop --host secondary.example.com:27017
높은 디스크 사용률, 높은 대기 시간 또는 긴 I/O 큐는 일반적으로 보조 노드가 충분히 빠르게 쓸 수 없음을 의미합니다. 이는 보조 노드에 더 저렴한 인스턴스 유형을 사용하거나, EBS 또는 네트워크 스토리지의 프로비저닝된 처리량이 낮거나, 백업 및 파일 시스템 스냅샷이 피크 애플리케이션 쓰기와 동시에 실행될 때 발생할 수 있습니다.
CPU도 중요할 수 있습니다. 특히 압축, 암호화, 문서 이동, 인덱스 유지 관리 또는 많은 작은 업데이트가 있는 워크로드에서 그렇습니다. 메모리 압력은 페이지 폴트, 캐시 변동 및 oplog 항목을 적용하려고 시도하면서 디스크에서 계속 읽는 보조 노드로 나타납니다.
실용적인 해결 방법은 일반적으로 지루합니다: 보조 노드에 프라이머리와 비슷한 스토리지와 CPU를 제공하고, 해당 호스트에서 경쟁 작업을 줄이거나, 무거운 읽기를 다른 곳으로 옮기십시오. 복제 세트 멤버는 무료 보고 용량이 아닙니다. 여전히 복제를 따라잡아야 합니다.
보조 노드에서의 읽기가 문제를 일으키는 경우
보조 노드를 사용한 읽기 확장은 유용하지만, 과도하게 사용하기 쉽습니다. 대규모 컬렉션을 스캔하는 대시보드 쿼리는 oplog 적용과 경쟁할 수 있습니다. 보조 노드는 여전히 읽기를 수락할 수 있지만, 동일한 CPU, 캐시 및 디스크가 사용자 쿼리에 사용되기 때문에 복제가 뒤처집니다.
지연된 멤버에서 프로파일러와 현재 작업을 확인하십시오:
db.currentOp({ active: true })
긴 읽기, 집계 작업 또는 유지 관리 스크립트가 보이면, 해당 보조 노드가 정말로 그 워크로드를 처리해야 하는지 결정하십시오. 보고의 경우 숨겨진 또는 전용 보조 노드가 더 적합할 수 있습니다. 애플리케이션 읽기의 경우 maxStalenessSeconds를 설정하여 드라이버가 너무 뒤처진 보조 노드를 피하도록 하십시오.
일관성이 중요한 경로의 경우 프라이머리 읽기를 사용하십시오. 예를 들어 로그인 상태, 체크아웃 확인, 비밀번호 변경, 계정 설정 및 사용자가 자신의 쓰기를 즉시 읽을 것으로 예상하는 모든 것이 있습니다. 보조 노드 읽기는 짧은 지연이 허용되는 데이터에 가장 적합합니다.
프라이머리가 버스트를 생성하는 경우
대규모 쓰기는 정상적인 보조 노드를 고장난 것처럼 보이게 할 수 있습니다. 대량 가져오기, 광범위한 다중 문서 업데이트, TTL 정리, 대규모 삭제 및 인덱스 변경은 적용하는 데 시간이 걸리는 oplog 활동의 버스트를 생성할 수 있습니다.
프라이머리에서 최근 작업을 확인하십시오:
db.currentOp({ active: true })
또한 애플리케이션 배포, 데이터 복구 작업, 백필 및 예약된 작업을 확인하십시오. 정확히 02:00에 시작되는 복제 지연은 종종 신비롭지 않습니다. 배치 작업입니다.
작업을 제어할 수 있는 경우 더 작은 청크로 분할하십시오. 예를 들어, _id 범위로 문서를 업데이트하고, 배치 사이에 일시 중지하고, 작업이 실행되는 동안 지연을 모니터링하십시오. bulkWrite를 사용하면 순서 없는 쓰기가 처리량을 향상시킬 수 있지만, 오류 처리는 명시적이어야 합니다. 실패가 부분적일 수 있기 때문입니다. 목표는 항상 프라이머리가 가능한 한 빨리 완료되도록 하는 것이 아닙니다. 목표는 복제 세트가 복구 여유를 잃지 않고 작업을 흡수할 수 있도록 하는 것입니다.
인덱스와 oplog 적용
정상적인 복제 세트에서 인덱스는 복제됩니다. 수동 작업, 유지 관리 실패 또는 잘못 복원된 노드로 인해 멤버 간에 인덱스가 다른 경우, 보조 노드는 업데이트 및 삭제를 적용하는 데 매우 느려질 수 있습니다. oplog 작업은 문서를 찾아야 할 수 있으며, 예상 인덱스가 없으면 보조 노드는 프라이머리보다 훨씬 더 많은 작업을 수행할 수 있습니다.
영향을 받는 컬렉션의 인덱스 정의를 비교하십시오:
db.orders.getIndexes()
프라이머리와 지연된 보조 노드에서 동일한 명령을 실행하십시오. 차이가 있다면, 더 많은 변경을 가하기 전에 이유를 찾으십시오. 대규모 인덱스를 다시 빌드하는 것은 그 자체로 부하를 생성할 수 있으므로, 조용한 기간에 계획하거나 차이가 광범위한 경우 알려진 양호한 소스에서 멤버를 다시 빌드하십시오.
백그라운드 인덱스 빌드가 모든 복제 문제를 해결한다는 오래된 조언을 사용하지 마십시오. MongoDB 인덱스 빌드 동작은 버전에 따라 변경되었으며, 올바른 운영 선택은 사용 중인 버전과 토폴로지에 따라 다릅니다. 실행 중인 정확한 버전에 대한 현재 서버 문서를 사용하십시오.
네트워크 문제는 일반적으로 다른 곳에서 볼 수 있습니다
네트워크 지연은 일반적으로 불안정한 하트비트, 간헐적인 오류 또는 특정 호스트 또는 지역 간의 낮은 처리량으로 나타납니다. 기본적인 확인은 여전히 도움이 됩니다:
ping primary.example.com
traceroute primary.example.com
그러나 낮은 핑 지연 시간이 충분한 대역폭을 증명하지는 않습니다. 복제는 처리량, 패킷 손실, 방화벽 검사, 교차 지역 링크 또는 시끄러운 공유 네트워킹에 의해 제한될 수 있습니다. 원격 보조 노드에만 지연이 나타나는 경우, 프라이머리와 동일한 지역의 보조 노드와 비교하십시오. 동일한 지역의 멤버가 정상이고 원격 멤버가 뒤처져 있다면, 토폴로지가 링크에 너무 많은 것을 요구하고 있을 수 있습니다.
교차 지역 복제 세트의 경우, 트레이드오프에 대해 솔직해지십시오. 재해 복구에 도움이 될 수 있지만, 지연 시간과 대역폭 제한에 더 노출됩니다. 원격 멤버가 읽기용인 경우, 지연 제어를 사용하고 로컬 보조 노드처럼 동작할 것이라고 가정하는 대신 장애 조치 동작을 테스트하십시오.
재시작 및 재동기화 조언에 주의하십시오
mongod를 다시 시작하면 일시적인 문제를 해결할 수 있지만, 노드가 oplog에서 떨어질 위기에 처한 경우 인시던트를 악화시킬 수 있습니다. 다시 시작하기 전에 oplog 윈도우와 현재 지연을 확인하십시오. 노드가 따라잡는 데 2시간이 필요하고 피크 트래픽 중 oplog 윈도우가 3시간에 불과하다면, 긴 재시작은 따라잡기 대신 초기 동기화로 이어질 수 있습니다.
초기 동기화는 보조 노드가 오래되었거나, 손상되었거나, 필요한 oplog 기록이 누락된 경우 유효한 복구 옵션입니다. 그러나 비용이 많이 듭니다. 데이터를 복사하고, 인덱스를 빌드하며, 동기화 소스에서 네트워크 및 디스크 리소스를 소비합니다. 프로덕션에서는 복제 세트가 장애를 견딜 수 있도록 충분한 투표 및 데이터 보유 멤버를 유지하기 위해 한 번에 하나의 멤버를 추가하거나 다시 빌드하는 것이 좋습니다.
멤버가 너무 뒤처져 따라잡을 수 없는 경우, 운영 표준에 맞는 신선한 백업 또는 스냅샷 기반 경로를 사용하십시오. 체크리스트에 있다고 해서 데이터 디렉토리를 삭제하지 마십시오. 멤버가 폐기 가능한지, 복제 세트가 재빌드를 견딜 수 있는지, 충분한 oplog 윈도우 또는 신뢰할 수 있는 초기 동기화 소스가 있는지 확인하십시오.
사용자와 운영자가 신경 쓰는 것에 대해 알림을 설정하십시오
좋은 알림은 모든 시스템에 대해 "복제 지연이 1초보다 큼"이 아닙니다. 일부 애플리케이션은 분석 읽기에서 30초를 허용할 수 있습니다. 다른 애플리케이션은 계정 상태에 대한 오래된 읽기를 허용할 수 없습니다. 알림 임계값은 사용 사례를 반영해야 합니다.
유용한 알림은 다음과 같습니다:
- 지속 기간 동안 애플리케이션 허용 오차 이상의 복제 지연.
- 가장 긴 예상 유지 관리 또는 복구 간격 미만의 oplog 윈도우.
- 예상보다 오래
RECOVERING,STARTUP2또는 비정상 상태인 보조 노드. - 데이터 보유 멤버의 디스크 I/O 포화.
- 멤버 간 하트비트 실패 또는 네트워크 오류.
대시보드는 쓰기 볼륨, 디스크 지연 시간, CPU, 메모리 압력 및 네트워크 처리량 옆에 지연을 표시해야 합니다. 지연 자체는 문제가 있음을 알려줍니다. 주변 그래프는 일반적으로 어떤 문제인지 알려줍니다.
실용적인 트라이지 순서
당직 중일 때 이 순서를 사용하십시오:
rs.status()로 지연되는 멤버를 확인하십시오.secondaryDelaySecs로 인해 지연이 의도적인지 확인하십시오.rs.printReplicationInfo()로 oplog 윈도우를 확인하십시오.- 지연을 쓰기 스파이크, 배치 작업 및 최근 배포와 비교하십시오.
- 지연된 보조 노드의 디스크, CPU, 메모리 및 로컬 쿼리 부하를 검사하십시오.
- 영향을 받는 멤버 간의 네트워크 오류 및 지연 시간을 확인하십시오.
- 멤버가 따라잡을 수 있는지, 부하를 제거해야 하는지, 더 많은 리소스가 필요한지, 아니면 다시 빌드해야 하는지 결정하십시오.
최상의 결과는 일반적으로 극적인 명령이 아닙니다. 병목 현상을 찾고 데이터 발산을 생성하지 않고 제거하는 것입니다. MongoDB 복제 지연은 용량 및 토폴로지 신호로 취급할 때 관리할 수 있습니다. 일반적인 MongoDB 실패가 아닙니다.