Post

개발자를위한레디스 8장 - 복제

복제

레디스에서 고가용성 확보

  • 복제 : 마스터 노드의 데이터를 복제본 노드로 실시간 복사하는 기능
  • 자동 페일오버 : 마스터 노드에서 발생한 장애를 감지해 레디스로 들어오는 클라리언트 연결을 자동으로 복제본 노드로 리디렉션 하는 기능

위의 두가지 모두 정상동작해야 고가용성을 확보할 수 있습니다.

레디스에서의 복제 구조

복제본 노드를 추가하는 이유

  • 마스터 데이터베이스가 다운되었을 때 대신 사용할 수 있는 여분의 복제본 필요
  • 트래픽을 복제본쪽으로 분산시켜 마스터 노드로의 트래픽을 감소시키는 역할
  • 백업을 복제본에서 수행하면 백업 작업이 서비스에 미치는 영향을 최소화

복제 구조 구성하기

복제본이 될 노드 B에서 REPLICAOF 커맨드를 입력해 마스터 노드의 정보를 입력하면 복제 연결이 시작됩니다.

1
REPLICAOF <master-ip> <master-port>

패스워드 설정

레디스 6.0이상부터 도입된 ACL 기능이 아닌 기본적인 패스워드를 사용해서 데이터를 복제할 때에는 masterauth 옵션에 패스워드를 입력해야합니다.

requirepass 옵션을 이용해 패스워드를 설정할 수 있으며, 비밀번호가 없으면 master에 연결해 데이터를 받아갈 수 없습니다.

복제본 노드에서 requirepass를 다른 값으로 설정해 각 레디스 노드에 접근할 때마다 다른 패스워드를 사용하게할 수도 있지만, 하나의 복제그룹에 속한 마스터와 복제본 노드는 같은 패스워드로 설정하는 것이 일반적입니다.

복제본 인스턴스의 설정파일을 직접 수정한 후 인스턴스를 재시작하거나, 실행중인 복제본 인스턴스에서는 아래의 방법으로 수정한 뒤 설정파일을 다시 작성할수 도 있습니다.

1
2
3
4
5
> CONFIG SET masterauth mypassword
OK

> CONFIG REWRITE
OK

복제 메커니즘

아래의 모든 과정은 자동으로 이뤄지며 사용자의 개입이 필요치 않습니다. 버전 7 이전에는 repl-diskless-sync옵션의 기본값이 no이며, 기본적으로 아래의 방식으로 복제 연결이 이뤄졌습니다.

  1. REPLICAOF 커맨드로 복제 연결을 시도
  2. 마스터 노드에서는 fork로 자식 프로세스를 새로 만든 뒤 RDB 스냅샷을 생성
  3. (2)번 과정 동안 마스터 노드에서 수행된 모든 데이터셋 변경 작업은 레디스 프로토콜 형태로 마스터의 복제 버퍼에 저장
  4. RDB 파일이 생성 완료되면 파일은 복제본 노드로 복사
  5. 복제본에 저장됐던 모든 내용을 모두 삭제한 뒤 RDB 파일을 이용해 데이터를 로딩
  6. 복제 과정 동안 버퍼링됐던 복제 버퍼의 데이터를 복제본으로 전달해 수행시킴

마스터 노드에서는 디스크에 RDB 파일을 생성하는 로그를 확인할 수 있습니다. 복제본 노드 에서는 마스터로부터 RDB 파일을 읽어오고, RDB 파일을 로드하는 과정의 로그를 확인할 수 있습니다.

위의 복제 과정에서 복제 속도는 디스크I/O 처리량에 영향을 받습니다.(마스터에서 RDB 파일을 저장하는 시간, 복제본에서 RDB파일을 읽어오는 과정 등)


버전 7 이후부터는 repl-diskless-sync옵션의 기본값이 yes이며, 디스크를 사용하지 않는 방식에서는 아래의 방식으로 복제가 이뤄집니다.

  1. REPLICAOF 커맨드로 복제 연결을 시도
  2. 마스터 노드는 소켓 통신을 이용해 복제본 노드에 바로 연결하며, RDB 파일은 생성됨과 동시에 점진적으로 복제본의 소켓에 전송
  3. (2)의 과정 동안 마스터 노드에서 수행된 모든 데이터셋 변경 작업은 레디스 프로토콜 형태로 마스터의 복제 버퍼에 저장
  4. 소켓에서 읽어온 RDB 파일을 복제본의 디스크에 저장
  5. 복제본에 저장된 모든 데이터를 모두 삭제한 뒤 RDB 파일 내용을 메모리에 로딩
  6. 복제 버퍼의 데이터를 복제본으로 전달해 수행시킴

마스터 노드에서는 디스크를 사용하지 않고 RDB 데이터를 보내는 로그를 확인할 수 있습니다. 복제본 노드 에서는 마스터로부터 디스크를 사용하지 않는 방식으로 RDB 파일을 읽어오고, RDB 파일을 로드하는 과정의 로그를 확인할 수 있습니다.

이 과정에서 복제본의 repl-diskless-load 옵션이 기본적으로 disabled이기 때문에 소켓에서 읽어온 RDB 스냅샷 데이터를 바로 메모리에 로드 하지않고, 일단 복제본 노드의 디스크에 저장하는 과정을 거칩니다. 복제본 노드는 마스터에서 가져온 데이터를 불러오기 전에 자신의 데이터를 모두 삭제하는 과정을 거쳐야 하는데, 이때 소켓 통신으로 받아온 RDB 데이터가 정상적인지를 미리 확인할 수 없기 때문에 모두 삭제하기 전 자신의 디스크에 데이터를 저장하는 과정을 선행함으로 데이터의 안정성을 확보할 수 있습니다.

비동기 방식으로 동작하는 복제 연결

정상적으로 복제 연결이 된 상태에서 마스터에서 복제본으로의 데이터 전달은 비동기 방식으로 동작합니다.

마스터에서 데이터를 입력하는 커맨드가 수행되면 레디스는 마스터 노드에서 커맨드를 처리한 이후 클라이언트에 OK를 보냅니다.

복제 ID

모든 레디스 인스턴스는 복제 ID를 가지고 있습니다. 복제 ID는 오프셋과 쌍으로 존재하며, 데이터가 수정되는 모든 커맨드를 수행할 때마다 오프셋이 증가합니다.

복제 연결을 시작하면 복제본의 replication id는 마스터의 replication id로 변경됩니다. 오프셋은 복제본에서 마지막으로 수행된 마스터의 오프셋을 의미하며, 레디스에서 replication id의 오프셋이 같을 때 두 노드는 정확히 일치된 상태라는 것을 의미합니다.

부분 재동기화

레디스는 부분 재동기화 기능을 사용해 안정적으로 복제 연결을 유지합니다. 재연결되면 복제본은 PSYNC 커맨드를 호출해 자신의 replication id와 오프셋을 마스터에 전달합니다.

복제 백로그 크기는 repl-backlog-size 파라미터로 설정할 수 있으며 기본값은 1MB입니다. 백로그 크기가 클수록 복제본이 부분 재동기화를 수행할 수 있는 시간이 길어집니다. 백로그는 1개 이상의 복제본이 연결된 경우에만 할당되며, repl-backlog-ttl만큼의 시간이 경과하면 메모리에서 백로그 공간을 삭제합니다.

백로그란?
Redis 복제에서 백로그는 마스터 노드와 슬레이브 노드 간의 연결이 끊어졌을 때, 재연결 시점에 부분 동기화를 수행하기 위해 사용되는 데이터입니다. 마스터는 일정 크기의 백로그 버퍼를 유지하며, 슬레이브와의 연결이 끊어졌다가 재연결될 때 이 백로그를 사용하여 변경된 데이터만 동기화하여 전체 동기화의 오버헤드를 줄입니다.
Redis 복제는 기본적으로 마스터 노드의 데이터를 슬레이브 노드로 복제하여 가용성을 높이고 읽기 성능을 향상시키는 기술입니다. 복제 과정에서 네트워크 단절 등으로 인해 마스터와 슬레이브 간 연결이 끊어질 수 있습니다. 이 경우, 백로그는 끊어진 동안 마스터에서 발생한 데이터 변경 사항을 저장하여 재연결 시점에 전체 데이터를 다시 복제하는 대신 변경된 부분만 동기화할 수 있도록 합니다.

Secondary 복제 ID

마스터 노드와의 복제가 끊어짐과 동시에 복제본은 새로운 복제 ID를 갖게 됩니다. 레디스가 2개의 복제 ID를 갖는 이유는 마스터로 승격되는 복제본 때문이며, 같은 복제 그룹 내에서 페일오버 이후 승격된 새로운 마스터에 연결된 복제본은 전체 재동기화를 수행할 필요가 없을 수 있습니다.

읽기 전용 모드로 동작하는 복제본 노드

버전 2.6 이후 레디스에서 복제를 구성하면 복제본은 기본으로 읽기 전용 모드로 동작합니다. 이 설정은 replica-read-only 옵션을 이용해 제어됩니다.

유효하지 않은 복제본 데이터

복제본의 데이터와 마스터의 데이터가 정확하게 일치하지 않은 경우의 데이터를, 유효하지 않은 데이터라고 합니다. 복제본의 동작 방식은 replica-serve-stale-data 파라미터를 이용해 제어할 수 있습니다. 기본값은 yes입니다.

  • yes: 유효하지 않다고 판단될 때에도 클라이언트로부터 들어오는 모든 읽기 요청에 데이터를 반환
  • no: 일부 기본 커맨드를 제외한 모든 커맨드에 대해 SYNC with master in progress라는 오류를 반환

백업을 사용하지 않는 경우에서의 데이터 복제

장애 상황은 아래와 같이 발생했다고 해봅시다.

  1. 백업 기능을 사용하지 않는 마스터와 복제본 노드가 존재
  2. 마스터 노드가 장애로 인해 종료됐지만, 레디스 프로세스를 자동 재시작하는 시스템에 의해 노드가 재부팅된다. 이때 메모리의 내용은 초기화됨
  3. 복제본 노드에는 데이터가 존재하지만, 마스터 노드로의 복제 연결을 시도
  4. 마스터에서 복제본으로 빈 데이터셋을 전달

위의 상황에서 만약 백업을 사용했다면 백업 파일을 자동으로 읽어오기 때문에 데이터가 복원됩니다.

자동 재시작 기능을 사용하지 않았다면 연결 설정을 마스터에서 복제본 노드로 변경해 데이터를 계속 사용할 수 있습니다.

데이터의 안정성을 위해 복제 기능을 사용할 경우 백업 기능을 사용하는 것이 좋습니다. 그렇지 않을 경우, 마스터에서는 인스턴스의 자동 재시작을 활성화하지 않는 것이 권장됩니다.

This post is licensed under CC BY 4.0 by the author.