환경: Redis 6.0 / Sentinel / 데이터 500GB 이상
Sentinel에서 sentinel failover mymaster 명령어로 수동 failover를 수행하면, 데이터가 거의 없고 backlog 설정이 충분한 환경에서도 partial resync가 아닌 full resync가 발생한다.
Before turning into a replica, using my own master parameters to synthesize a cached master:
I may be able to synchronize with the new master with just a partial transfer
Discarding previously cached master state.
Full resync from master
connection with replica client id lost
sentinel failover는 내부적으로 선택된 replica에게 SLAVEOF NO ONE을 보내는 비협조적(uncoordinated) 방식이다. master는 자신이 교체될 것을 모르기 때문에 내부 쓰기를 계속하고, 이로 인해 offset 불일치가 발생한다. 이것은 버전과 관계없이 동일하게 발생하는 구조적 문제이다.
SLAVEOF NO ONE 전송 → 새 master로 승격SLAVEOF <new-master> 전송 → replica로 전환connection with replica client id lost 발생이전 master의 offset이 새 master의 second_repl_offset보다 크면, 새 master는 "이 replica가 요청하는 offset은 내가 알고 있는 분기 시점보다 앞서 있다"고 판단하여 partial resync를 거부한다. 데이터가 거의 없는 환경에서도 failover 과정의 시간 차이 동안 Sentinel의 PING/INFO 교환만으로 offset 차이가 발생한다.
master_replid2가 000...000으로 보이는 것은 full resync가 완료된 후 replica가 새 master의 replid로 갱신되면서 초기화된 결과이다.
버전과 관계없이 Sentinel 환경에서는 CLIENT PAUSE WRITE로 쓰기를 먼저 중단하여 master의 offset 증가를 멈춘 후 SENTINEL FAILOVER를 수행해야 한다. 이렇게 하면 새 master의 second_repl_offset과 이전 master의 offset이 일치하여 partial resync가 가능해진다.
Sentinel이 failover 주체가 되므로 +switch-master 이벤트가 즉시 발행되고, 클라이언트 전환도 정상적으로 이루어진다.
사전 준비로 터미널 2개를 미리 준비한다.
redis-cli -h <master-ip> -p 6379)redis-cli -h <sentinel-ip> -p 26379)| 순서 | 터미널 | 명령어 | 설명 |
|---|---|---|---|
| 1 | A (master) | INFO replication | slave0의 lag=0 확인 (0과 1 반복은 정상) |
| 2 | B (sentinel) | SENTINEL failover mymaster 타이핑만 (엔터 치지 않음) | 미리 준비 |
| 3 | A (master) | CLIENT PAUSE 30000 WRITE | OK 확인 후 즉시 Step 4 |
| 4 | B (sentinel) | 엔터 (미리 타이핑한 명령 실행) | Step 3과 간격 최소화 |
| 5 | A (master) | INFO replication | role:slave 변경 확인 |
| 6 | A (master) | CLIENT UNPAUSE | 안전하게 해제 |
| 구분 | CLIENT PAUSE + failover | 그냥 sentinel failover |
|---|---|---|
| 쓰기 중단 시간 | 약 5~10초 | 약 5~10초 (비슷) |
| failover 후 상태 | partial resync → 즉시 정상 | full resync → 수 시간 부하 |
| master 부하 | 없음 | RDB fork로 메모리/CPU/IO 폭증 |
| OOM 위험 | 없음 | copy-on-write로 최대 ~1TB |
| replica 가용성 | 즉시 정상 | sync 완료까지 불안정 |
| 데이터 정합성 | 보장 | offset 차이만큼 유실 가능 |
Redis Cluster 환경의 CLUSTER FAILOVER는 이 문제가 발생하지 않는다. replica가 master에게 failover를 요청하면 master가 CLIENT PAUSE WRITE를 실행하고, replica가 offset을 따라잡은 후 Cluster 투표를 통해 전환된다. 협조적(coordinated) 방식이므로 offset 불일치가 없고, Cluster 구성이 자동 전파되어 추가 조치도 불필요하다.
Sentinel 환경의 SENTINEL FAILOVER는 master에게 알리지 않고 replica에 SLAVEOF NO ONE을 보내는 비협조적 방식이므로 offset 불일치가 발생하며, 이를 방지하려면 수동으로 CLIENT PAUSE WRITE를 먼저 수행해야 한다. 이 문제는 Sentinel이 내부적으로 협조적 전환을 지원하지 않는 구조적 한계이며, GitHub issue #13118, #13917에서 개선이 제안된 상태이나 아직 공식 반영되지 않았다.
redis-cli -h <노드-ip> INFO replication
확인할 값: master_replid, master_replid2, master_repl_offset, second_repl_offset, repl_backlog_first_byte_offset
grep -iE "psync|partial|full|resync|replid|offset|accept|reject" <new-master-log-path>
다음 중 하나가 출력된다:
Partial resynchronization not accepted: Replication ID mismatch → replid 불일치Partial resynchronization not accepted: Requested offset for second ID was X, but I can reply up to Y → offset 초과grep -iE "psync|partial|full|resync|cached|discard|turning|pause" <old-master-log-path>
grep -iE "failover|switch-master|promoted|selected" <sentinel-log-path>