레디스의 PSYNC에 대해 알게 되었고, 이를 정리하기 위해 글을 작성하게 되었습니다.
1. PSYNC
PSYNC(Partial Resynchronization)는 레디스 2.8부터 도입된 복제 명령어로, 마스터와 레플리카 간의 동기화 효율을 높이기 위해 사용됩니다.
레디스의 복제는 기본적으로 마스터-레플리카 구조를 따르며, 마스터에서 발생한 변경 사항을 레플리카로 전달하여 데이터 일관성을 유지합니다. 초기 레디스에서는 SYNC 명령만 사용해 복제를 수행했는데, 이는 레플리카가 연결될 때마다 항상 전체 데이터를 다시 받아야 했기 때문에, 네트워크 부하가 크고 성능에도 악영향을 주었습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
+---------+ SYNC 요청 +----------+
| Replica | --------------------------> | Master |
+---------+ +----------+
│ │
│ │
│ │
│ 매번 전체 데이터(RDB) 전송 │
│ <--------------------------------------│
│ │
│ │
│ │
│ │
─────────────────────────────────────────────────────
이를 개선하기 위해 PSYNC가 등장하게 되었습니다. 레플리카가 마스터에 다시 연결될 때 이전에 받았던 데이터의 위치 정보 를 함께 전달하면, 마스터는 그 이후에 변경된 데이터만 전송 합니다. 이를 통해 전체 데이터를 다시 복제하지 않아도 되어, 복제 속도를 높이고, 시스템 리소스 사용량도 줄일 수 있죠.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Replica 재접속]
│
▼
PSYNC <replicationId, offset> 요청
│
▼
[Master가 확인: backlog에 데이터 있고, ID 일치하는가?]
│
├── Yes ───────────────▶ [Partial Resync]
│ └─ 변경된 데이터만 전송
│
└── No ───────────────▶ [Full Resync]
├─ RDB 생성 및 전체 전송
└─ 이후 명령 버퍼 전송
2. 동작 원리
PSYNC는 레플리카가 재접속할 때, 마지막으로 받은 복제 ID와 오프셋을 마스터에 전달하면, 마스터가 해당 시점 이후의 변경 분만 빠르게 전송하는 원리로 동작합니다. 이를 위해서는 레플리카가 전달하는 복제 ID가 마스터와 일치 해야 하며, 레플리카가 마지막으로 받은 오프셋 이후의 데이터가 마스터의 복제 백로그(Buffer)에 남아 있어야 하는 두 가지 조건이 충족되어야 합니다.
복제 ID(Replication ID) 일치: 레플리카가 기억하는 마스터의 복제 ID가 현재 마스터의 ID와 같아야 합니다.오프셋(Offset) 유효: 레플리카가 요청한 오프셋 이후의 데이터가 마스터의 복제 백로그(Replication Backlog)에 남아 있어야 합니다.
2-1. 복제 ID와 오프셋
복제 ID는 마스터의 데이터셋 이력을 식별하는 고유한 문자열이며, 오프셋은 전송된 데이터의 byte 수를 의미합니다. 이 둘의 조합은 특정 시점의 데이터 상태를 정확히 나타내는 기준이 됩니다. 레디스는 이중 복제 ID를 사용해, 장애 조치나 재시작 이후에도 레플리카들이 새로운 마스터와 부분 동기화를 시도할 수 있도록 돕습니다.
1
2
3
4
5
6
7
8
9
10
11
[Replica] [Master]
┌────────────┬──────────────┐ ┌──────────────────────┬──────────────────────┐
│ ID │ 8eaa1c70... │──────▶│ current_repl_id │ prev_repl_id │
│ Off │ 123456789 │──────▶│ 8eaa1c70... │ abcd1234... │
└────────────┴──────────────┘ └──────────────────────┴──────────────────────┘
│ │
│ │
└────────────▶ PSYNC 요청 ──────────────────────▶ │
│
Backlog: [ ... | ... | ... ]
Offset: 123456789
이중 복제 ID는 레디스 4.0부터 도입된 기능으로, 마스터 노드가 현재와 이전 두 개의 복제 ID를 함께 관리하는 방식 입니다. 마스터가 장애 조치나 재시작으로 복제 ID가 바뀌더라도, 레플리카는 이전 ID를 이용해 부분 동기화를 계속 시도할 수 있습니다.
1
2
3
4
5
6
role:slave
master_host:172.23.0.7
master_port:7004
master_link_status:up
master_replid:7278525adcba750aeb7e9b283f5dab898cca0012 # 현재 마스터의 복제 ID
master_replid2:0000000000000000000000000000000000000000 # 이전 마스터의 복제 ID
2-2. Replication Backlog
복제 백로그는 마스터의 메모리에 유지되는 고정 크기의 순환 버퍼(Circular Buffer) 입니다. 마스터는 레플리카에게 전송하는 모든 명령어 데이터를 이 백로그에 기록합니다. 레플리카가 재연결하여 특정 오프셋 이후의 데이터를 요청하면, 마스터는 백로그에서 해당 데이터를 찾아 전송합니다. 만약 레플리카의 연결이 너무 오래 끊겨 그사이에 발생한 데이터의 양이 백로그 크기를 초과하면, 레플리카가 필요로 하는 오래된 데이터는 이미 덮어쓰여 사라진 상태가 됩니다. 이 경우 부분 동기화는 실패합니다.
1
2
3
4
5
6
7
8
9
10
# 백로그는 마스터 레디스의 메모리에만 존재. 서버 꺼지면 같이 사라짐.
┌─────────────────────────────────────────────────────────────────────────┐
│ Master │
│ │
│ Replication ID Replication Backlog (메모리, 순환 버퍼) │
│ ┌───────────────┐ ┌──────┬──────┬──────┬──────┬──────┬──────┐ │
│ │ 8eaa1c70... │◀─────▶ │DATA1 │DATA2 │DATA3 │ ... │DATAx │ │ │
│ └───────────────┘ └──────┴──────┴──────┴──────┴──────┴──────┘ │
│ (replication-backlog-size - 메모리 유지) │
└─────────────────────────────────────────────────────────────────────────┘
2-3. SYNC
만약 이 중 하나라도 충족되지 않으면 PSYNC는 실패하고, 전체 동기화가 수행됩니다. 이 경우 마스터는 전체 데이터를 RDB 파일로 덤프하여 레플리카에 전송하고, 이후 발생한 명령들을 스트리밍하여 보내는 방식으로 동기화합니다. 마스터는 전체 데이터를 다시 복제하기 위해 RDB 스냅샷을 생성하고, 이를 레플리카에 전송하죠. 그런 다음, 복제 중 새로 발생한 명령들을 추가로 전송하여 완전한 복제 상태를 만듭니다.
1
2
3
4
5
6
+---------+ +---------------------+ +---------+
| Master | ====> | RDB Snapshot 생성 | ====> | Replica |
+---------+ +---------------------+ +---------+
│ ▲
│ │
└──────────── 명령 버퍼(추가 명령 전송) ──────────────┘
3. 운영 시 주의사항
안정적인 복제 환경을 위해 PSYNC 운영 시 다음 사항들을 유의해야 합니다.
- Backlog 크기 부족
- 마스터 재시작 또는 Failover
- 복제 ID 관리
- 네트워크 품질
3-1. Backlog 크기 부족
레디스의 부분 동기화(PSYNC)는, 마스터 서버의 메모리 내에 있는 백로그에 필요한 데이터가 남아 있을 때만 정상적으로 동작합니다. 만약 레플리카가 네트워크 장애 등으로 인해 마스터와 장시간 연결이 끊겨 있었거나, 그사이에 마스터에서 처리된 명령의 양이 백로그 버퍼 용량(replication-backlog-size)을 초과했다면, 레플리카가 마지막으로 받지 못한 데이터는 이미 백로그에서 덮어써져 사라지게 됩니다.
1
2
3
4
repl_backlog_active:1 # 백로그 활성화 여부 (1: 활성)
repl_backlog_size:1048576 # 백로그 크기 (Byte 단위, 예시는 1MB)
repl_backlog_first_byte_offset:86 # 백로그의 첫 바이트 offset
repl_backlog_histlen:28966 # 현재 백로그에 남아 있는 데이터 크기(바이트)
3-2. 마스터 재시작 또는 Failover
백로그는 메모리에만 존재 하므로 마스터 레디스 서버가 다운되거나 재시작될 때 내용이 유실될 수 있습니다. 또한 장애 조치가 발생해 새로운 마스터가 선출되는 경우, 복제 ID가 변경되거나 백로그 데이터가 맞지 않으면 레플리카는 부분 동기화를 사용할 수 없습니다. 이처럼 마스터의 장애나 재시작 이후에는 반드시 전체 동기화를 거쳐야만 레플리카가 정상적으로 데이터를 받을 수 있으니, 장애 복구나 유지보수 시 전체 동기화로 인한 부하를 염두에 둬야 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[마스터 장애/재시작/Failover]
Master (재시작/장애로 백로그 소실, 복제ID 변경)
│
└─── Master가 새로 시작됨
│ (백로그=없음, 복제ID=새값)
│
Replica(레플리카, 재접속)
│
├─ PSYNC(이전 복제ID, offset 전달)
│ (마스터에 이전 복제ID 질의)
│
├─ Master 응답: "복제ID/백로그 불일치, PSYNC 불가"
│
└─ 전체 동기화(SYNC) 요청
│
└─ Master가 RDB 전체 생성 및 전송 → Replica
└─ (이후 명령 버퍼 계속 전송)
3-3. 복제 ID 관리
레디스 4.0 버전부터는 마스터가 현재 복제 ID와 이전 복제 ID, 두 가지를 관리하는 이중 복제 ID 체계를 도입했습니다. 이 덕분에 failover나 마스터 재시작 이후에도 레플리카가 부분 동기화를 시도할 가능성이 조금 더 높아졌습니다. 하지만, failover나 레플리카가 너무 오래 연결이 끊겨 있었던 경우에는 이중 복제 ID로도 데이터 연속성이 보장되지 않아, 부분 동기화가 불가능할 수 있습니다. 이 경우, 결국 전체 동기화가 필요해질 수 있습니다.
1
* Partial resynchronization not accepted: Replication ID mismatch (Replica asked for '39ba0c3263fd29bcec9aece97c634d1250b60dba', my replication IDs are '7278525adcba750aeb7e9b283f5dab898cca0012' and 'c7b61223f5ece8b771133ce02ecc83759dbea18b')
3-4. 네트워크
PSYNC 방식은 효율적 부분 동기화를 지원하지만, 네트워크에 따라 동기화 지연 이나 패킷 손실 이 발생할 수 있습니다. 예를 들어, 레플리카와 마스터 사이의 네트워크가 불안정하거나 대역폭이 좁은 경우, 백로그 크기가 작으면 그 사이에 백로그가 덮어써져 PSYNC가 실패할 가능성이 높아집니다. 따라서 네트워크의 상태가 좋지 않으면 부분 동기화가 원활하게 이뤄지지 않아, 전체 동기화가 반복적으로 발생할 수 있으니, 이를 주의하도록 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Replication Backlog: 순환 버퍼(메모리 한도 내에서 데이터 저장)
# 백로그 크기 = 8칸, 오래된 데이터는 새 데이터로 덮어써짐
[시점1]
┌────┬────┬────┬────┬────┬────┬────┬────┐
│ A │ B │ C │ D │ E │ F │ G │ H │
└────┴────┴────┴────┴────┴────┴────┴────┘
시간이 지나면서 계속 명령이 쌓임 → 가장 오래된 데이터부터 덮어씀
[시점2]
┌────┬────┬────┬────┬────┬────┬────┬────┐
│ I │ J │ K │ L │ E │ F │ G │ H │
└────┴────┴────┴────┴────┴────┴────┴────┘
레플리카가 네트워크 장애로 뒤늦게 PSYNC 요청 시
→ 이미 필요한 데이터(A~D)가 사라져 부분 동기화 불가
→ 전체 동기화(SYNC) 필요
4. 정리
레디스 PSYNC는 마스터와 레플리카 간의 효율적인 부분 동기화를 지원하여, 네트워크 부하를 줄이고 성능을 향상시키는 기능입니다. 이를 통해 레플리카가 마스터에 재접속할 때, 마지막으로 받은 데이터 이후의 변경 사항만 빠르게 전송받을 수 있습니다.