개요
Redis 복제는 마스터-복제본(master-replica) 구조를 기반으로 하는 단순하고 사용하기 쉬운 시스템입니다. 복제본 Redis 인스턴스는 마스터 인스턴스의 정확한 사본이 됩니다.
복제본은 연결이 끊어질 때마다 자동으로 마스터에 재연결하며, 마스터에 무슨 일이 일어나든 관계없이 정확한 사본이 되려고 시도합니다.
복제 작동 방식
Redis 복제는 3가지 주요 메커니즘으로 작동합니다:
1. 정상 상태에서의 복제
- 마스터와 복제본이 잘 연결되어 있을 때
- 마스터가 복제본에게 명령어 스트림을 전송하여 업데이트
- 클라이언트 쓰기, 키 만료/삭제, 데이터셋 변경 등을 복제
2. 부분 재동기화 (Partial Resynchronization)
- 마스터와 복제본 간 연결이 끊어졌을 때
- 복제본이 재연결하여 누락된 명령어 부분만 가져오려고 시도
3. 전체 재동기화 (Full Resynchronization)
- 부분 재동기화가 불가능할 때
- 마스터가 전체 데이터의 스냅샷을 생성하여 복제본에 전송
- 더 복잡한 프로세스
비동기 vs 동기 복제
기본: 비동기 복제
- 기본값으로 비동기 복제 사용
- 낮은 지연시간과 높은 성능 제공
- 복제본이 주기적으로 마스터에게 처리된 데이터량을 비동기적으로 확인
동기 복제 (선택적)
WAIT
명령어를 사용하여 특정 데이터의 동기 복제 요청 가능- 지정된 수의 복제본에서 쓰기 확인을 보장
- 완전한 강일관성은 제공하지 않음 (장애 조치 시 쓰기 손실 가능)
Redis 복제의 중요한 특징
✅ 핵심 특성
- 비동기 복제: 기본적으로 비동기 복제 사용
- 다중 복제본: 하나의 마스터가 여러 복제본을 가질 수 있음
- 연쇄 복제: 복제본이 다른 복제본에 연결 가능 (Redis 4.0+)
- 논블로킹: 마스터 측에서 복제는 논블로킹
- 확장성: 읽기 전용 쿼리를 위한 확장성 제공
⚠️ 주의사항
- 마스터 지속성 필수: 마스터에서 지속성을 꺼두면 위험
- 자동 재시작 위험: 지속성이 꺼진 상태에서 자동 재시작은 데이터 손실 위험
복제 ID와 오프셋
복제 ID (Replication ID)
- 각 Redis 마스터가 가지는 대형 의사 무작위 문자열
- 데이터셋의 특정 히스토리를 표시
- 인스턴스가 처음부터 시작하거나 복제본이 마스터로 승격될 때 새로 생성
오프셋 (Offset)
- 복제 스트림의 각 바이트마다 증가하는 값
- 복제본의 상태를 업데이트하는 데 사용
복제 ID + 오프셋 = 정확한 데이터셋 버전
# 예시: 두 인스턴스가 같은 복제 ID와 오프셋을 가지면 동일한 데이터
Replication ID: abc123...
Offset: 1000
기본 설정
복제본 설정
# redis.conf에 추가
replicaof 192.168.1.1 6379
런타임 설정
# 명령어로 설정
REPLICAOF 192.168.1.1 6379
디스크리스 복제 (Diskless Replication)
# 디스크 없이 직접 네트워크로 RDB 전송
repl-diskless-sync yes
repl-diskless-sync-delay 5
Read-only 복제본
기본 설정 (권장)
# 읽기 전용 모드 (기본값)
replica-read-only yes
❌ 쓰기 가능한 복제본의 문제점
- 데이터 불일치: 마스터와 복제본 간 불일치 발생
- 예측 불가능한 동작: 명령어 전파 시 다른 결과 초래
- 메모리 누수: TTL 키 만료 처리 문제 (4.0 이전)
대안 명령어 (Redis 7.0+)
# 기존 쓰기 명령어 대신 읽기 전용 버전 사용
SORT_RO # SORT 대신
EVAL_RO # EVAL 대신
EVALSHA_RO # EVALSHA 대신
SUNION # SUNIONSTORE 대신
ZINTER # ZINTERSTORE 대신
인증 설정
마스터 패스워드 설정
# 복제본 설정 파일에 추가
masterauth <password>
런타임 설정
CONFIG SET masterauth <password>
최소 복제본 수 설정
안전성을 위한 설정
# 최소 N개의 복제본이 연결되어야만 쓰기 허용
min-replicas-to-write 2
min-replicas-max-lag 10
작동 방식
- 복제본이 매초 마스터에게 ping 전송
- 마스터가 각 복제본의 마지막 ping 시간 기억
- 지연시간이 M초 이하인 N개 이상의 복제본이 있어야 쓰기 허용
키 만료 처리
마스터 주도 만료
- 복제본은 키를 직접 만료시키지 않음
- 마스터가 키를 만료시키고 DEL 명령어를 복제본에 전송
- 복제본은 논리적으로 만료된 키를 읽기 작업에서 존재하지 않는 것으로 처리
Lua 스크립트에서의 만료
- Lua 스크립트 실행 중에는 키 만료가 수행되지 않음
- 스크립트 실행 시간 동안 시간이 "정지"된 것으로 간주
Docker/NAT 환경 설정
문제점
- Docker의 포트 매핑으로 인한 주소 불일치
- NAT 환경에서 실제 IP와 논리적 IP의 차이
해결책
# 복제본이 마스터에게 알릴 IP와 포트 설정
replica-announce-ip 5.5.5.5
replica-announce-port 1234
고급 기능
부분 동기화 (Redis 4.0+)
- 장애 조치 후에도 부분 재동기화 가능
- 복제본이 이전 마스터의 복제 ID와 오프셋을 기억
Maxmemory 설정
# 복제본에서 maxmemory 무시하지 않기
replica-ignore-maxmemory no
모니터링 명령어
INFO 명령어
# 복제 관련 정보만 조회
INFO replication
ROLE 명령어
# 복제 상태 조회 (더 컴퓨터 친화적)
ROLE
복제 사용 시나리오
✅ 적합한 용도
- 읽기 확장성: 읽기 전용 쿼리를 여러 복제본으로 분산
- 데이터 안전성: 데이터 백업 및 고가용성
- 지리적 분산: 다른 지역의 복제본으로 지연시간 감소
- 분석 워크로드: 무거운 분석 작업을 복제본에서 수행
⚠️ 주의할 점
- 쓰기 확장성 제한: 모든 쓰기는 마스터에서만 가능
- 지연시간: 비동기 복제로 인한 복제 지연
- 복잡성: 장애 조치 시 추가 로직 필요