애플리케이션이 복제 셋과 어떻게 상호작용하는지 살펴보자
- 연결 및 장애 조치를 수행하는 방법
- 쓰기 시 복제 대기하는 방법
- 올바른 멤버에 읽기 요청을 라우팅하는 방법
12.1 클라이언트-복제 셋 연결동작
복제 셋이면 기본적으로 몽고DB 클라이언트는 프라이머리에 연결되고, 모든 트래픽을 프라이머리에 라우팅한다
복제 셋에 대한 연결은 단일 서버에 대한 연결과 비슷하다
드라이버에서 MongoClient를 사용하고, 연결할 드라이버를 위한 시드 목록을 제공하자
시드 목록은 단순히 서버 주소 목록이다
시드(Seed)는 애플리케이션이 데이터를 읽고 쓸 복제 셋의 멤버다
모든 멤버를 나열할 필요는 없다 (드라이버는 시드에 연결되면 다른 멤버들을 발견한다)
모든 몽고DB 드라이버는 서버 검색 및 모니터링 사양을 준수한다
복제 셋의 토폴로지를 지속적으로 모니터링해 애플리케이션이 셋의 모든 멤버에 도달하는 기능에서 변화를 감지한다
드라이버는 어떤 멤버가 프라이머리인지 알기 위해 셋을 모니터링한다
몽고DB 3.6부터 서버와 모든 몽고DB 드라이버는 재시도 가능한 쓰기 옵션을 지원한다
재시도 가능한 쓰기라면 드라이버는 자동으로 최대 1번 재시도하는 전략을 따른다
일시적인 네트워크 문제로 인한 문제를 극복할 수 있다
12.2 쓰기 시 복제 대기하기
복제 셋에 어떤 일이 발생하든 쓰기가 지속되려면 각 쓰기가 복제 셋 멤버 과반수에 전파돼야 한다
withConcern을 사용한다
몽고DB 2.6부터 쓰기 작업과 통합됐다
12.4 세컨더리로 읽기 전송
드라이버에서 read preference를 설정해 다른 옵션을 구성할 수도 있다
(기본적으로 모든 요청은 프라이머리로 라우팅)
읽기 요청을 세컨더리에 보내면 일반적으로 좋지 않다
몇몇 특정 상황에서는 의미가 있지만, 일반적으로 모든 트래픽은 프라이머리로 전송해야 한다
(1) 일관성 고려 사항
매우 일관된 읽기가 필요할 때는 세컨더리로부터 읽기를 수행하면 안 된다
세컨더리는 보통 프라이머리의 몇 밀리초 이내에 있어야 한다. 하지만 이는 보장되지 않는다
최신 데이터가 필요하다면 세컨더리에서 읽지말자
읽기 요청을 항상 프라이머리로 보내려면 읽기 선호도를 primary로 설정하자 (default 값이다)
하지만 프라이머리가 없으면 오류가 발생한다
(2) 부하 고려 사항
많은 사용자가 부하를 분산하려고 읽기를 세컨더리로 전송한다
예를 들어 서버가 초당 1만 개의 쿼리를 처리할 수 있다고 하자
3만 개를 처리하게 하려면, 2개의 세컨더리를 구성해서 부하를 일부 처리하도록 할 수 있다
하지만 이런 확장은 위험하다. 뜻하지 않게 시스템에 과부하를 유발할 수 있고, 과부하가 발생하면 회복하기 어렵기 때문이다
만약 세컨더리 중 하나가 손상된다고 가정해보자
다른 멤버들은 가각 처리 가능한 부하를 100% 처리하고 있다
손상된 멤버를 재구축해 사용하려면 다른 서버 중 하나로부터 데이터를 복사해야 한다
서버가 과부하되면 종종 수행 속도가 느려지고, 복제 셋의 수용 능력을 더욱 낮추며, 다른 멤버에 더 많은 부하를 줘서 점점 느려지게 하는 악순환이 생긴다
과부하는 복제를 느려지도록 하며, 남은 세컨더리 역시 뒤처질 수 있다
결국 모두 과부하에 걸릴 가능성이 있다
서버의 개수를 더 늘리면 세컨더리가 하나 다운되더라도 복제 셋은 과부하가 되지 않는다
부하를 분산하는 더 좋은 방법은 샤딩이며 나중에 다시 보도록 하자
(3) 세컨더리에서 읽기를 하는 이유
몇몇 경우에는 애플리케이션 읽기를 세컨더리로 전송하는 것이 합리적이다
예를 들어 프라이머리가 다운되더라도 애플리케이션이 지속적으로 읽기 작업을 수행하기를 원할 수 있다
(해당 읽기가 유효한지는 신경 쓰지 않는다)
이는 읽기를 세컨더리에 분산하는 가장 일반적인 경우다
복제 셋이 프라이머리를 잃으면 사용자는 임시로 읽기 전용 모드를 원한다
이 때 읽기 선호도 설정은 primaryPreferred 이다
세컨더리로부터 읽기와 관련된 일반적은 문제로, 지연율이 낮은 읽기가 중요하다
nearest로 읽기 선호도를 설정함으로써, 드라이버에서 복제 셋 멤버까지의 평균 핑 시간을 기반으로 지연율이 가장 낮은 멤버에 요청을 라우팅할 수 있다
secondaryPreferred는 세컨더리에 읽기 요청을 보낸다
이용 가능한 세컨더리가 없으면 프라이머리에 요청을 보낸다
어느 정도 읽기 요청이 프라이머리로부터 발생한다면 primary를 사용하자
다른 읽기는 데이터가 최신이 아니어도 괜찮다면 primaryPreferred를 사용하자
요청에 일관성보다는 낮은 지연율이 필요하다면 nearest를 사용하자
'MongoDB' 카테고리의 다른 글
[MongoDB] Ch14 - 샤딩 소개 (1) | 2022.02.21 |
---|---|
[MongoDB] Ch13 - 관리 (0) | 2022.01.28 |
[MongoDB] Ch11 - 복제 셋 구성 요소 (0) | 2022.01.21 |
[MongoDB] Ch10 - 복제 (0) | 2022.01.18 |
[MongoDB] Ch9 - 애플리케이션 설계 (0) | 2022.01.11 |
댓글