MongoDB 레플리케이션 개요

이번에는 “MongoDB 레플리케이션"에 대해 알아보겠다.

레플리케이션 (Replication)

“레플리케이션(Replication)“는 데이터를 여러 데이터베이스 서버에 복사하여 중복성과 가용성을 제공하는 메커니즘이다. 보존하는 데이터 센터가 다른 경우 장애 혹은 재해에 대책이 된다. 또한, 동일한 데이터가 되고 있으므로 읽기가 많은 어플리케이션에서는 부하 분산을 시킬 수도 있다.

MongoDB에서의 레플리케이션

MongoDB는 동일한 데이터를 보유하는 데이터베이스 인스턴스를 “복제본 셋"라는 단일 그룹으로 관리한다. MongoDB는 이 레플리케이션 셋의 작동 방식으로 중복성과 가용성을 제공한다.

프라이머리 서버는 모든 쓰기 작업을 받는 서버로 데이터에 대한 변경 사항을 기록하고 로그에 남긴다. 세컨더리 서버는 프라이머리 서버의 작업 로그를 복사하고 적용하여 프라이머리 서버와 동일한 데이터 상태를 만든다. 만약 프라이머리 서버에 장애가 발생하면 적절한 세컨더리 서버가 프라이머리 서버로 선임되어 서비스를 계속하게 된다.

MongoDB 레플리케이션

레프리카셋(복제본 셋, Replicaset) 맴버

MongoDB의 레프리카셋(Replicaset)에 포함된 맴버 유형은 다음과 같은 세 가지 유형이 있다.

  • 프라이머리(Primary)
  • 세컨더리(Secondary)
  • 아비터(Arbiter)

각각에 대해 아래에서 자세히 소개한다.

프라이머리(주, Primary) 서버

레프리카셋 중에 하나만 존재하는 쓰기 가능한 서버이다. 프라이머리 서버에 쓰기 작업 정보는 로그 oplog로 남아 있으며, 이 작업 로그가 세컨더리 서버로 전송되어 복사된다.

프라이머리 서버가 어떤 이유로든 문제가 생기면, 나머지 세컨더리 서버 중 다음 프라이머리 서버가 투표로 선임된다.

세컨더리(보조, Secondary) 서버

기본 서버의 작업 로그를 기반으로 데이터를 업데이트하는 읽기 전용 서버이다. 세컨더리 서버를 여러 대 준비하여 많은 양의 읽기 작업을 수행할 수 있다.

클라이언트로부터의 데이터 읽기는 기본적으로 세컨더리 서버 우선으로 읽기에 수행되고, 즉시 요구되는 데이터만 프라이머리 서버 우선으로 읽기를 수행한다.

세컨더리 서버의 기본 설정에는 우선 순위(Priority), 숨겨진(Hidden), 지연(Delayed)의 3가지가 있다.

  • 우선순위(Priority)
    Priority: 0를 지정하면 프라이머리 서버로 승격하지 않는다. 우선순위가 0보다 큰 값이 설정된 서버에서 프라이머리 서버를 선임한다. 또한 우선 순위가 높은 값이 설정된 서버가 우선적으로 프라이머리 서버로 선임된다.
  • 숨겨진(Hidden)
    프라이머리 서버에서 작업 로그를 복사하여 데이터를 최신화하지만, 클라이언트 응용 프로그램에서는 보이지 않는 설정이다. 클라이언트 응용 프로그램에서 볼 수 없으므로 다른 서버에 비해 부하가 낮다. 숨겨진 설정으로 한 서버는 데이터 분석이나 백업 등 통상 업무와 다른 전용 단말로 이용한다.
  • 지연(Delayed)
    프라이머리 서버에서 작업 로그를 복사하여 데이터를 반영하지만, 프라이머리 서버보다 지정된 시간만큼 지연시켜 반영한다. 프라이어미 서버보다 지연시켜 반영시킴으로써 뭔가 조작 실수를 일으켜 버렸을 때의 복구에 이용할 수 있도록 한다.

아비터(중재, Arbiter) 서버

레프리카셋에서 투표 권한이 있는 서버를 홀수로 만들기 위해 추가하는 조정용 서버이다. 아비터 서버 자체에는 데이터가 없으며, 프라이머리 서버가 문재가 생겼을 때 발생하는 새로운 프라이머리 서버의 선임으로 투표하는 것이 주요 역할이다. 자신이 프라이머리 서버가 되지 않기 때문에 Priority: 0를 지정해 둔다.

레프리카셋 구성

레프리카셋에는 최대 50대의 멤버가 포함될 수 있으며, 그 중 최대 7대까지 투표권을 가진다. 투표 권한이 있는 서버 수는 홀수가 되도록 설계한다. 부족한 경우에는 중재자인 아비터를 추가하고 조정한다.

최소 레프리카셋은 3대 구성으로, 다음과 같은 구성을 할 수 있다.

  • 프라이머리, 세컨더리 2대
  • 프라이머리, 세컨더리, 아비터

지리적으로 떨어진 데이터 센터에 멤버를 배치하면 더 높은 가용성을 얻을 수 있다.

프라이머리, 세컨더리 2대

이 패턴은 세컨더리 서버 2대 모두가 프라이어 머리 서버가 될 수 있으므로 가용성이 높은 구성이 된다.

보통 2대의 세컨더리 서버에 완전한 복사본이 만들어진다. 프라이머리 서버가 문제가 발생하면 남아 있는 두 개의 세컨더리 서버가 투표를 수행하고 둘 중 하나가 프라이머리 서버로 승격된다.

프라이머리, 세컨더리 2대

프라이머리, 세컨더리, 아비터

이른바 서버 2대 구성이다. 실제로 동작은 프라이머리 서버와 세컨더리 서버의 2대이고, 아비터 서버는 장애 조치(failover)가 수행 될 시에 투표에 참가할 정도이다(그러나, 세컨더리에 아비터 승격에 추천되지 않으므로, 관리용 서버 등 물리적으로 다른 낮은 사양 서버에 위치한다).

이 패턴의 경우는 아비터 서버에는 데이터 복사되지 않으므로 전체 복사본은 세컨더리 서버에만 적용된다. 프라이머리 서버에 문제가 생기면 프라이머리 서버 투표가 수행되지만 필연적으로 남아 있는 세컨더리 서버가 프라이머리 서버로 승격된다.

프라이머리, 세컨더리, 아비터

자동 장애 조치(failover)

레프리카셋은 자동 장애 조치(failover)로 고가용성을 제공한다. 구체적으로는 프라이머리 서버가 응답하지 않을 때, 세컨더리 서버에서 다음 프라이머리 서버를 선임하고 선임된 세컨더리 서버가 프라이머리 서버로 승격함으로써 실현된다.

각 멤버는 2초 간격으로 하트비트(ping)를 수행한다. 10초 동안 응답을 받지 못하면 해당 서버를 불량 서버로 표시한다. 프라이머리 서버가 불량 서버로 설정되면 나머지 세컨더리 서버에서 다음 주 서버의 선임이 시작된다.

서버가 투표를 할 때 우선 순위가 높은 서버가 우선적으로 세컨더리 서버로 선임된다. 우선 순위(Priority)가 낮은 서버가 선임된 상태로 보다 높은 우선도(Priority)의 서버가 유효하게 되었을 경우, 다시 우선도(Priority)가 높은 서버가 프라이머리 서버가 되도록 투표가 수행 된다.

투표를 하지 않는 맴버은 우선순위(Priority)를 0으로 설정한다. 하나의 레프리카셋에서 투표권은 7개까지이므로, 그 이상의 보조 서버를 용기하는 경우는 우선도(Priority)를 0으로 투표권(votes)도 0으로 설정한 서버로 한다.

데이터 읽기/쓰기

데이터의 읽기 쓰기도 MongoClient의 생성시에 설정 옵션으로 지정할 수 있다. 쓰기에 대한 설정은 w, j, wtimeout 3가지, 읽기에 대한 설정은 readPreference, readConcern.level 2가지가 있다.

var {MongoClient, ReadPreference} = require("mongodb");
 
var URL = "mongodb://localhost:27017/test";
 
MongoClient.connect(URL, {
  // 쓰기 설정
  w: "majority",
  j: true,
  wtimeout: 5000,
  // 읽기 설정
  readPreference: ReadPreference.SECONDARY_PREFERRED
  readConcern: {
    level: "local"
  }
}, (client) => {
  client.close();
});

데이터 쓰기

쓰기는 Write Concern 구성에서 레프라카셋에 포함된 서버의 몇 대까지 쓰기 처리를 전파할지 여부를 지정한다.

w

설정값 설명
<number> 지정한 대수까지 기입되는 것을 보증한다.
"majority" 투표 권한이 있는 서버의 과반수에 기록되도록 한다.

j

설정값 설명
true 디스크에 쓸 때까지 수행한다.
false 기본값. 메모리에 쓰기만 보장한다.

wtimeout

설정값 설명
<number> 쓰기 시간이 초과되는 시간(밀리초)을 지정한다. 설정하는 경우 1보다 큰 값을 지정한다. 0을 지정하면 시간 초과 처리가 수행되지 않는다.

데이터 읽기

읽기는 Read Preference 설정으로 어떤 서버에서 우선적으로 데이터를 로드할지 설정할 수 있다.

readPreference

설정값 설명
primary 기본 모드. 주 서버에서 가져온다.
primaryPreferred 대부분의 경우 기본 서버에서 가져오지만 주 서버에 액세스할 수 없는 경우 보조 서버에서 가져온다.
secondary 보조 서버에서 가져온다.
secondaryPreferred 대부분의 경우 보조 서버에서 가져오지만 보조 서버에 액세스할 수 없는 경우 주 서버에서 가져온다.
nearest 복제 세트의 유형에 관계없이 대기 시간이 최소 서버에서 검색된다.

readConcern.level
어떤 데이터를 가져올지 지정한다.

설정값 설명
"local" 기본적으로 기본을 읽으십시오. 인스턴스의 최신 데이터를 가져온다. 복제본 세트의 대부분에 쓰여진 데이터인지 여부는 보장하지 않는다.
"available" 기본적으로 보조를 읽으십시오. 인스턴스의 최신 데이터를 가져온다. 복제본 세트의 대부분에 쓰여진 데이터인지 여부는 보장하지 않는다.
"majority" 대부분의 멤버에 기록된 데이터의 최신 데이터를 가져온다.
"linearizable" 모든 쓰기가 끝난 후 롤백되지 않는 데이터를 가져온다.

정리

이번에는 「MongoDB의 복제」에 대해 정리하였다. 포인트는 다음과 같다.

  • 쓰기는 프라이머리 서버만 가능하다.
  • 프라이머리 서버에 문제가 생기면 남은 세컨더리 서버가 프라이어머리 서버로 승격된다.

참고 자료