-
개발자를 위한 레디스 - 8장: 복제NoSQL/Redis 2024. 5. 6. 16:11
레디스에서 고가용성을 확보하기 위한 두 가지 기능.
※ 가용성: 전체 시간 중 서비스를 정상적으로 사용할 수 있는 시간
- 복제: 마스터 노드의 데이터를 복제본 노드로 실시간 복사하는 기능
- 자동 페일오버: 마스터 노드에서 발생한 장애를 감지해 레디스로 들어오는 클라이언트 연결을 자동으로 복제본 노드로 리디렉션 하는 기능
1. 레디스에서의 복제 구조
레디스 복제본 노드의 사용 이유.
- 마스터 노드가 다운되었을 경우를 대비
- 일부 트레픽을 복제본으로 돌려 부하 분산
- 백업을 복제본에서 수행하여 서비스 영향도 최소화
레디스는 멀티 마스터 구조를 지원하지 않으므로 복제본 노드에서는 읽기 작업만 수행할 수 있다.
1) 복제 구조 조성하기
# 복제본이 될 노드에서 다음 명령어 수행 REPLICAOF <master-ip> <master-port>
2. 복제 메커니즘
1) 디스크를 사용하는 복제 옵션 (repl-diskless-sync: no → 7버전 이전에서 디폴트)
디스크를 사용하는 방식에서의 복제 연결 메커니즘 2) 디스크를 사용하지 않는 복제 옵션 (repl-diskless-sync: yes → 7버전 이후부터 디폴트)
디스크를 사용하지 않는 방식을 사용할 때의 복제 연결 메커니즘 ※ 디스크를 사용하는 방식에서는 복제 요청에 의해 RDB가 생성되는 도중 다른 노드의 복제 연결 요청이 들어오면 이 연결은 큐에 저장되어 기존 RDB 파일의 저장이 완료되면 여러 복제본이 한 번에 복제 연결 시작이 가능했지만, 디스크를 사용하지 않는 방식에서는 이미 하나의 복제복으로 복제 연결이 시작된 경우 복제 과정이 끝나기 전 까지 다른 복제본과의 연결은 수행될 수 없으며, 다른 복제본들은 복제 연결이 끝날 때 까지 큐에서 대기해야 한다.
이를 방지하기 위해 repl-diskless-sync-delay 5 옵션(기본값 5)를 사용할 수 있는데 새로운 복제 연결이 들어오면 기본 5초를 기다린 뒤 복제 연결을 시작한다는 의미다. 이 기간 내에 또 다른 복제 연결이 들어오면 마스터는 여러 복제본으로 소켓 통신을 연결해 한 번에 여러 개의 복제본에 RDB 파일을 전송할 수 있다. 보통 네트워크 유실로 인해 재동기화 요청일 발생할 경우 마스터는 한 번에 여러 개의 복제본에서 복제 연결이 들어오기에 이 옵션을 활성화하는것이 좋다.
3) 비동기 방식으로 동작하는 복제 연결
정상적으로 복제 연결이 된 상태에서 마슽에서 복제본으로의 데이터 전달은 비동기(async) 방식으로 동작한다.
따라서 아래 그림의 (2) 과정 이후로 마스터 노드가 비정상 종료된 경우 복제본 노드에 데이터가 전달되지 않았으므로 유실될 가능성이 존재한다.
4) 복제 ID
모든 레디스 인스턴스는 무작위 스트링 값의 복제 ID를 가지고 있으며 오프셋과 쌍으로 존재하는데 레디스 내부의 데이터가 수정되는 모든 커맨드를 수행할 때마다 오프셋이 증가한다.
// 마스터에서 명령어 수행 > INFO REPLICATION # Replication role:master connected_slaves:1 slave0:ip=127.0.0.1,port=6002,state=online,offset=709,lag=0 master_replid:e3b06d3eba522894a240a8a9ce3e808dd5ccfd7a master_replid2:0000000000000000000000000000000000000000 master_repl_offset:807 ... // 레플리카에서 명령어 수행 > INFO REPLICATION # Replication role:slave master_host:127.0.0.1 master_port:6001 ... master_replid:e3b06d3eba522894a240a8a9ce3e808dd5ccfd7a // 복제 연결이 시작되면 마스터의 replid를 replid로 사용 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:801 // 복제본에서 마지막으로 수행된 마스터의 오프셋 ...
5) 부분 재동기화
복제 연결이 끊길 때마다 마스터에서 RDB 파일을 새로 내려 복제본에 전달하는 과정을 거친다면 네트워크가 불안정한 상황에서 복제 기능을 사용하는 레디스 성능이 급격하게 나빠질 것이다. 이를 방지하기 위해 부분 재동기화 기능을 사용하여 안정적으로 복제 연결을 유지한다.
마스터는 백로그 버퍼라는 메모리 공간에 복제본에 전달한 커맨드 데이터들을 저장해두는데 복제 연결이 끊긴 뒤 잠시 후 재연결되면 복제본에서 PSYNC 커맨드를 호출해 자신의 repl id값과 오프셋을 마스터에 전달한다.
이 때, 마스터의 백로그에 소실된 오프셋의 내용이 저장돼 있다면 RDB 파일을 새로 저장할 필요 없이 백로그에 저장된 내용을 복제본에 전달하여 부분 재동기화를 진행할 수 있다.
하지만, 마스터의 백로그 버퍼에 원하는 데이터가 남아 있지 않거나 복제본의 repl id가 현재의 마스터와 일치하지 않다면 전체 재동기화(full resync)를 시도하게 된다.
복제 백로그 크기는 repl-backlog-size 파라미터로 설정 가능하면 기본값은 1MB이다. 백로그는 1개 이상의 복제본이 연결된 경우에만 할당되며, repl-backlog-ttl만큼의 시간이 경과하면 메모리에서 백로그 공간을 삭제한다.
6) Secondary 복제 ID
레디스는 2개의 복제 ID를 가지고 있는데 이는 마스터로 승격되는 복제본 때문이며, 같은 복제 그룹 내에서 페일오버 이후 승격된 새로운 마스터에 연결된 복제본은 전체 재동기화를 수행할 필요가 없을 수 있다.
마스터 노드와의 복제가 끊어짐과 동시에 복제본은 새로운 repl id를 갖게 된다. (마스터 복구 완료 시 역동기화가 되면 안되기 때문)
같은 복제 그룹에서 새로운 마스터가 선출되는 경우 노드 C가 B에 복제 연결이 될 때, 두 노드의 master_replid2가 같기 때문에 C노드는 B노드에 부분 재동기화를 시도한다.
7) 읽기 전용 모드로 동작하는 복제본 노드
버전 2.6이후 레더스에서 복제를 구성하면 복제본은 기본으로 읽기 전용 모드로 동작한다. 즉, 복제본에는 새로운 데이터를 저장하는것이 불가능하고 읽기 커맨드만 수행 가능하단 것. (이 설정은 replica-read-only 옵션으로 제어할 수 있다.)
특정 상황에서 마스터 노드에서 수행하기에 오래 걸리는 연산 결과를 테스트하기 위한 용도로 복제본의 replica-read-only 옵션을 해제하고 싶을 수 있다. 이 경우 복제본 노드의 데이터가 변경되더라도 복제본이 재시작되거나 커넥션 유실로 인한 전체 재동기화가 발생하면 복제본에서 수행한 데이터는 사라지기 때문에 유의해야한다.
또한, 복제본에 데이터를 직접 쓰더라도 해당 복제본에 연결된 다른 복제본으로는 전파되지 않는다.
8) 유효하지 않은 복제본 데이터
유효하지 않은 복제본 데이터란 마스터와의 데이터와 정확히 일치하지 않는 경우의 데이터를 의미한다. 이 때 복제본의 동작 방식은 replica-serve-stale-data 파라미터를 이용해 제어할 수 있다. 기본값은 yes로 복제본의 데이터가 유효하지 않다 판단되어도 클라이언트의 모든 읽기 요청에 데이터를 반환한다. 이 값을 no로 설정한다면 INFO, CONFIG, PING 등 일부 기본 커맨드를 제외한 모든 커맨드에 대해 SYNC with master in progress 라는 오류를 반환한다.
9) 백업을 사용하지 않는 경우에서의 데이터 복제
레디스에서 복제를 사용하는 경우 마스터와 복제본에서 백업 기능을 사용하는것이 좋다. 만약 백업을 사용하지 않으려면 재부팅 후 레디스가 자동 재시작되지 않도록 설정할 것을 권장한다.
복제 구조에서 백업을 설정하지 않았을 경우 만약 백업을 사용했다면 두 번째 행에서 레디스가 재부팅되었을 때 백업 파일을 자동으로 읽어오기 때문에 데이터가 복원되며, 복원된 내용이 복제본으로 전달되었을 것이다.
자동 재시작 기능을 사용하지 않았다면 복제본 노드에 데이터가 존재하기 때문에 애프리케이션 연결 설정을 마스터에서 복제본 노드로 변경해 데이터를 계속 사용할 수 있다. (혹은 복제본 노드에서 데이터를 새로 백업받아 마스터 노드에 전달한 뒤 마스터 노드를 시작시키면 복제본 노드에 저장된 내용으로 데이터가 복원될 수 있다.)
'NoSQL > Redis' 카테고리의 다른 글
개발자를 위한 레디스 - 5장: 레디스를 캐시로 사용하기 (0) 2024.05.06 개발자를 위한 레디스 - 7장: 레디스 데이터 백업 방법 (0) 2024.05.02 개발자를 위한 레디스 - 4장: 레디스 자료구조 활용 사례 (1) 2024.04.28 개발자를 위한 레디스 - 3장: 레디스 기본 개념 (2) 레디스에서 키를 관리하는 법 (0) 2024.04.11 개발자를 위한 레디스 - 3장: 레디스 기본 개념 (1) 레디스의 자료 구조 (0) 2024.04.11