
이제 7단계 — Redis Cluster → Redis Cluster 동기화로 넘어가겠습니다.
이번 단계부터가 현재 실제 환경과 가장 직접적으로 연결되는 핵심 구간입니다.
기준 환경은 계속 동일하게 잡겠습니다.
온프레미스 K8s
Source Redis Cluster
3 Master + 3 Replica
│
│ RedisShake
▼
Target Redis Cluster
3 Master + 3 Replica
Redis Cluster는 데이터를 하나의 Master가 모두 들고 있는 구조가 아니라,
총 16,384개의 Hash Slot을 여러 Master가 나눠 담당합니다.
Redis 공식 문서도 Key를 CRC16(key) mod 16384 방식으로 Slot에 매핑한다고 설명합니다. Redis
🟥 7단계 — Redis Cluster → Redis Cluster 동기화
7.1 먼저 전체 구조
예를 들어 Source가:
Source Redis Cluster
Shard 1
Master 1
Slot 0 ~ 5460
│
Replica 1
Shard 2
Master 2
Slot 5461 ~ 10922
│
Replica 2
Shard 3
Master 3
Slot 10923 ~ 16383
│
Replica 3
Target도:
Target Redis Cluster
Shard 1
Master 1
│
Replica 1
Shard 2
Master 2
│
Replica 2
Shard 3
Master 3
│
Replica 3
라고 하겠습니다.
전체 Migration은:
SOURCE
M1 M2 M3
│ │ │
│ │ │
└───┬───┴───┬───┘
│
▼
┌──────────────┐
│ RedisShake │
│ Pod │
└──────┬───────┘
│
▼
M1 M2 M3
TARGET
입니다.
7.2 Standalone과 가장 큰 차이
Standalone에서는:
Source 1대
│
▼
RedisShake
│
▼
Target 1대
였습니다.
하지만 Cluster는:
Source
M1
M2
M3
모두 데이터가 다릅니다.
예:
M1
user:100
session:200
M2
product:100
cart:300
M3
order:500
payment:100
따라서 RedisShake가:
M1만 읽음
하면 전체 데이터의 일부만 Migration됩니다.
7.3 RedisShake는 Cluster를 어떻게 읽을까?
Source 설정을:
[sync_reader]
cluster = true
address = "source-redis:6379"
로 합니다.
cluster=true가 핵심입니다.
RedisShake는 초기 Cluster Node에 접속한 뒤 Cluster topology를 파악하고,
Source의 Shard 수만큼 Standalone Reader를 만들어 병렬로 읽습니다.
공식 아키텍처 문서도 Cluster Reader가 Source shard 수에 맞춰 Reader를 생성하고 각 shard에서 병렬로 데이터를 읽는다고 설명합니다. Tair Open Source
쉽게 보면:
RedisShake
┌──────────┼──────────┐
│ │ │
Reader1 Reader2 Reader3
│ │ │
▼ ▼ ▼
M1 M2 M3
입니다.
7.4 Reader별로 Full + Incremental을 수행
각 Source Master마다:
M1
│
├─ RDB Full
└─ Incremental Stream
│
▼
Reader1
M2
│
├─ RDB Full
└─ Incremental Stream
│
▼
Reader2
M3
│
├─ RDB Full
└─ Incremental Stream
│
▼
Reader3
가 됩니다.
RedisShake의 sync_reader는 Replica처럼 Master에 연결해 Full RDB + Incremental AOF stream을 받아 처리합니다. Tair Open Source
7.5 중요한 점: Replica 데이터는 별도로 또 Migration하지 않는다
Source가:
M1 → R1
M2 → R2
M3 → R3
라고 하겠습니다.
Replica는 Master의 같은 데이터를 가지고 있습니다.
따라서 기본적으로:
M1 데이터
+
R1 데이터
둘 다 Target으로 복사
하는 게 아닙니다.
보통 Source Cluster의 Primary/Master shard 기준 데이터를 읽습니다.
M1 ─┐
M2 ─┼─→ RedisShake
M3 ─┘
Replica는 Source HA 용도입니다.
7.6 Target Cluster에서는 어떻게 저장될까?
RedisShake가 Source에서:
SET user:100 kim
이라는 데이터를 읽었습니다.
Target은 Cluster입니다.
Target이 Key를 다시 계산합니다.
user:100
│
▼
Hash Slot 계산
│
▼
예: Slot 2500
│
▼
Target Master 1
다른 Key:
product:500
│
▼
Slot 8000
│
▼
Target Master 2
입니다.
즉 RedisShake가 단순히:
Source M1 → Target M1
Source M2 → Target M2
Source M3 → Target M3
로 물리 복사하는 구조는 아닙니다.
7.7 이 부분이 정말 중요하다 ⭐
RedisShake는 Source의 Redis 파일을 Target 동일 Master에 복사하는 도구가 아닙니다.
정확하게는:
Source M1
Source M2
Source M3
│
▼
Redis Commands
│
▼
Target Cluster
│
▼
Target Slot 기준으로 재배치
입니다.
그래서 Source와 Target의 Master 수가 같을 필요도 없습니다.
예:
Source
3 Master
↓
RedisShake
↓
Target
6 Master
도 원리상 가능합니다.
Target의 Slot 배치에 따라 Key가 분산됩니다.
7.8 Source 3 Master → Target 6 Master 예
Source:
M1
Slot 0~5460
M2
5461~10922
M3
10923~16383
Target은 6 Master:
TM1
0~2730
TM2
2731~5460
TM3
5461~8191
TM4
8192~10922
TM5
10923~13652
TM6
13653~16383
일 수 있습니다.
그러면 Source M1의 데이터도 Target에서는:
Source M1
│
├─ 일부 → TM1
└─ 일부 → TM2
처럼 나뉠 수 있습니다.
7.9 Target 설정
Target도 Cluster이므로:
[redis_writer]
cluster = true
address = "target-redis:6379"
입니다.
공식 RedisShake Writer 문서도 Target이 Cluster이면 cluster=true를 설정하고, address에는 Cluster 노드 중 하나를 초기 주소로 지정할 수 있다고 설명합니다. Tair Open Source
전체 최소 설정:
[sync_reader]
cluster = true
address = "source-redis:6379"
sync_rdb = true
sync_aof = true
[redis_writer]
cluster = true
address = "target-redis:6379"
입니다.
7.10 K8s에서는 Initial Service만 연결되면 끝인가?
아닙니다.
이게 Cluster Migration의 가장 중요한 네트워크 포인트입니다.
예:
RedisShake
│
▼
source-redis Service
│
▼
Source M1
여기까지 성공했다고 합시다.
RedisShake가 Cluster 정보를 확인해서:
M1 = 10.244.1.10:6379
M2 = 10.244.2.20:6379
M3 = 10.244.3.30:6379
를 얻었습니다.
그 다음 RedisShake가 실제로:
10.244.1.10:6379
10.244.2.20:6379
10.244.3.30:6379
에 연결할 수 있어야 합니다.
따라서:
Initial Service 접근 성공 ≠ Cluster Migration 준비 완료
입니다.
7.11 Source 쪽 통신 요구사항
RedisShake 기준:
RedisShake
│
├─ Source 초기 Endpoint :6379
├─ Source Master 1 :6379
├─ Source Master 2 :6379
└─ Source Master 3 :6379
모두 가능해야 합니다.
Target도:
RedisShake
│
├─ Target 초기 Endpoint :6379
├─ Target Master 1 :6379
├─ Target Master 2 :6379
└─ Target Master 3 :6379
가 되어야 합니다.
7.12 같은 K8s Cluster라면
예:
Namespace: redis-source
Namespace: migration
Namespace: redis-target
이라면 RedisShake Pod가:
source-redis.redis-source.svc.cluster.local
와:
target-redis.redis-target.svc.cluster.local
에 접근합니다.
Pod별 DNS를 쓰는 구조라면:
redis-0.redis-headless.redis-source.svc.cluster.local
redis-1.redis-headless.redis-source.svc.cluster.local
redis-2.redis-headless.redis-source.svc.cluster.local
등에도 접근할 수 있어야 합니다.
7.13 서로 다른 K8s Cluster라면 난이도가 크게 올라간다
예:
운영센터 K8s
Source Redis Cluster
│
│ IDC Network
▼
DR센터 K8s
RedisShake + Target
이라고 하겠습니다.
Source Cluster가 RedisShake에게:
10.244.1.10
10.244.2.20
10.244.3.30
같은 Source K8s 내부 Pod IP를 알려줬는데 DR센터에서 해당 IP를 라우팅할 수 없다면:
Initial Connection ✅
Cluster topology ✅
각 Master Connection ❌
이 됩니다.
그래서 Cross-K8s Cluster Migration에서는 Redis Cluster가 광고하는 주소가 RedisShake에서 Routable한지가 핵심입니다.
7.14 Target Cluster 상태부터 확인해야 한다
Target이 정상 Redis Cluster인지 먼저 확인합니다.
예:
redis-cli -h target-redis -p 6379 CLUSTER INFO
중요한 항목:
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
입니다.
Redis 공식 문서에 따르면 cluster_state=ok는 Cluster가 정상적으로 요청을 받을 수 있음을 의미하며, 정상적인 Slot 할당에서는 cluster_slots_assigned가 16384여야 합니다. Redis
7.15 Source도 똑같이 확인
redis-cli -h source-redis -p 6379 CLUSTER INFO
최소:
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
를 봅니다.
Migration을 시작하기 전에 Source 자체 Cluster가 깨져 있다면 RedisShake 문제가 아니라 Source 문제부터 해결해야 합니다.
7.16 CLUSTER NODES 확인
redis-cli -h source-redis -p 6379 CLUSTER NODES
여기서:
Master
Replica
Node 주소
Slot
FAIL 여부
를 확인합니다.
예:
node-A ... master ... 0-5460
node-B ... master ... 5461-10922
node-C ... master ... 10923-16383
node-D ... slave node-A
node-E ... slave node-B
node-F ... slave node-C
이런 구조입니다.
7.17 왜 Node 주소를 꼭 봐야 하나?
RedisShake가 이 topology 정보를 기반으로 각 Source Shard에 접근하기 때문입니다.
예를 들어:
CLUSTER NODES
M1 192.168.10.10:6379
M2 192.168.10.11:6379
M3 192.168.10.12:6379
라면 RedisShake에서:
nc -zv 192.168.10.10 6379
nc -zv 192.168.10.11 6379
nc -zv 192.168.10.12 6379
같은 방식으로 실제 연결 가능 여부를 검증하는 것이 좋습니다.
7.18 이제 Full Sync
RedisShake를 실행하면 Source Shard별로:
Source M1 ─ RDB ─┐
Source M2 ─ RDB ─┼──→ RedisShake
Source M3 ─ RDB ─┘
Full 데이터를 받습니다.
RedisShake는 이를 임시 disk에 저장하고 RDB를 Redis command로 파싱해서 Target에 보냅니다. Tair Open Source
7.19 Full 중 Source Write는 계속 발생
Application이 계속 Source를 사용합니다.
Application
│
▼
Source Cluster
SET
HSET
DEL
INCR
...
Full RDB 처리 중 발생한 변경은 Incremental stream으로 이어집니다.
Source M1 ─ Full + Incremental ─┐
Source M2 ─ Full + Incremental ─┼→ RedisShake
Source M3 ─ Full + Incremental ─┘
그래서 서비스 중단 없이 Target을 따라잡게 만드는 것이 sync_reader의 핵심입니다. Tair Open Source
7.20 Incremental 단계
Full이 완료돼도 RedisShake는 계속 실행됩니다.
Source
SET A
DEL B
HSET C
INCR D
│
▼
RedisShake
│
▼
Target
Target Cluster는 각 Key의 Slot에 맞게 담당 Master로 명령을 처리합니다.
7.21 Cluster에서는 Lag도 Shard별로 확인
예:
M1 Lag
거의 0
M2 Lag
거의 0
M3 Lag
5GB
이라면:
Migration 완료 ❌
입니다.
M3가 아직 Source를 못 따라잡았기 때문입니다.
RedisShake Cluster Reader는 각 Source shard를 별도 Reader로 병렬 처리하기 때문에 특정 shard만 병목이 될 수 있습니다. Tair Open Source
7.22 왜 한 Shard만 느릴 수 있나?
예:
M1 Write
20MB/s
M2 Write
30MB/s
M3 Write
300MB/s
이라면 M3가 Hot Shard입니다.
또는:
M3
Large Key 다수
M3 Node CPU 95%
M3 Network 병목
일 수도 있습니다.
그래서:
전체 Redis Dataset = 3TB
만 보는 것보다:
M1 0.5TB
M2 0.7TB
M3 1.8TB
처럼 Shard skew를 확인해야 합니다.
7.23 Target의 Slot 배치가 Source와 같아야 하나?
반드시 같지는 않습니다.
Source:
3 Master
Target:
6 Master
도 가능합니다.
중요한 것은 Target Cluster 자체가:
16384 Slots
정상 배치
되어 있는 것입니다.
Redis Writer는 Target이 Cluster일 때 Cluster mode를 사용하여 명령을 적절한 노드에 전달합니다. Tair Open Source
7.24 다만 Multi-Key Command는 주의 ⚠️
Redis Cluster에서는 한 명령이 여러 Key를 사용한다면 보통 해당 Key들이 같은 Hash Slot에 있어야 합니다.
예를 들어:
MSET key1 value1 key2 value2
에서 key1, key2가 서로 다른 Slot이면 문제가 될 수 있습니다.
RedisShake Writer 공식 문서도 Target이 Cluster인 경우 Source에서 전달되는 multi-key 명령의 Key가 동일 Slot 조건을 만족해야 한다고 주의합니다. Tair Open Source
이 때문에 Redis Cluster 애플리케이션에서는 Hash Tag:
{user:100}:profile
{user:100}:cart
같은 방식을 사용하기도 합니다.
7.25 Redis 버전도 확인
예:
Source
Redis 7.x
Target
Redis 6.x
처럼 Target이 더 낮은 버전이면 Source에서 사용하는 명령이나 데이터 형식을 Target이 지원하지 못할 수 있습니다.
RedisShake Writer 문서도 가능한 한:
Target Redis Version ≥ Source Redis Version
방향을 권장합니다. Tair Open Source
따라서 보통:
Redis 6 → Redis 7
✅
Redis 7 → Redis 6
⚠️
관점으로 봅니다.
7.26 Target은 가능하면 비워두고 시작
신규 Migration이면:
Target
Empty
상태가 관리하기 쉽습니다.
왜냐하면 기존 Target에 같은 Key가 있으면 Source에서 들어오는 값과 충돌할 수 있기 때문입니다.
예:
Source
user:100 = kim
Target
user:100 = park
Migration 이후 어떤 값이 남아야 하는지 명확한 정책이 필요합니다.
그래서 기본 Migration에서는 신규/비어 있는 Target이 가장 단순합니다.
7.27 실제 shake.toml 예
현재 환경을 단순화하면:
[sync_reader]
cluster = true
address = "source-redis.redis-source.svc.cluster.local:6379"
username = ""
password = "SOURCE_PASSWORD"
tls = false
sync_rdb = true
sync_aof = true
[redis_writer]
cluster = true
address = "target-redis.redis-target.svc.cluster.local:6379"
username = ""
password = "TARGET_PASSWORD"
tls = false
핵심은:
sync_reader.cluster = true
redis_writer.cluster = true
입니다.
Source와 Target 모두 Redis Cluster이기 때문입니다. Tair Open Source
7.28 실행
K8s 기준:
kubectl apply -f redis-shake-configmap.yaml
kubectl apply -f redis-shake-secret.yaml
kubectl apply -f redis-shake-pod.yaml
Pod:
kubectl get pod -n redis-migration
RedisShake 로그:
kubectl logs \
-n redis-migration \
redis-shake \
-f
에서:
Source 연결
Cluster topology
PSync
RDB
Writer
Incremental
Error
을 확인합니다.
7.29 Migration 전 점검 순서
실무에서는 RedisShake부터 실행하지 않습니다.
먼저:
① Source Cluster 정상?
② Target Cluster 정상?
③ Source 16384 Slot 정상?
④ Target 16384 Slot 정상?
⑤ Master/Replica 상태 정상?
⑥ RedisShake → Source 각 Master 접근?
⑦ RedisShake → Target 각 Master 접근?
⑧ Disk/PVC 충분?
⑨ Source/Target Redis 버전 확인
⑩ ACL/Password 확인
을 확인합니다.
7.30 명령어로 보면
Source Cluster 상태
redis-cli \
-h source-redis \
-p 6379 \
CLUSTER INFO
Source Node 정보
redis-cli \
-h source-redis \
-p 6379 \
CLUSTER NODES
Target
redis-cli \
-h target-redis \
-p 6379 \
CLUSTER INFO
redis-cli \
-h target-redis \
-p 6379 \
CLUSTER NODES
정상 Cluster라면 전체 16,384 Slot이 할당되어 있어야 합니다. Redis
7.31 데이터 개수는 어떻게 비교?
Cluster에서는 특정 Master에서 그냥:
DBSIZE
한 번만 실행하면 해당 Node 데이터 개수만 볼 수 있으므로 전체 Cluster 비교로 오해하면 안 됩니다.
예:
M1 DBSIZE = 3M
M2 DBSIZE = 4M
M3 DBSIZE = 5M
이면 전체 개념적으로:
약 12M Keys
입니다.
따라서 Source/Target 비교도 Master별 합산해서 보는 것이 좋습니다.
7.32 그렇다고 Key Count만 같으면 끝인가?
아닙니다.
예:
Source
10,000,000 Keys
Target
10,000,000 Keys
이어도:
Value 다름
TTL 다름
Data Type 다름
가능합니다.
따라서 검증은 단계적으로:
① Key Count
② Sample Key
③ Value
④ Type
⑤ TTL
⑥ 필요 시 전체 정합성 검사
로 갑니다.
7.33 Cluster 상태 변화도 주의해야 한다
Migration 도중 Source에서:
M1 장애
↓
R1 승격
이 발생할 수 있습니다.
또는:
Slot Resharding
Node 추가/삭제
같은 topology 변화가 발생할 수 있습니다.
RedisShake 공식 Migration Mode 문서는 장기간 동기화나 topology 변경을 계속 추적하는 용도로 RedisShake를 보는 것은 주의해야 한다고 설명합니다. Tair Open Source
따라서 Migration Window 동안 가능하면:
Cluster Resharding
Scale-Out/In
계획 Failover
같은 변경 작업은 피하는 것이 좋습니다.
7.34 Migration 중 Source Application은 계속 Source를 본다
Application
│
▼
Source Cluster
│
▼
RedisShake
│
▼
Target Cluster
이 상태입니다.
Target에는 Application Write를 넣지 않습니다.
즉 RedisShake Migration은 기본적으로:
Source → Target
단방향
입니다.
7.35 Cutover 직전
Full Sync가 끝났습니다.
Full ✅
Incremental도 따라갑니다.
M1 Lag ↓
M2 Lag ↓
M3 Lag ↓
충분히 따라잡았다면:
① Application Write 제어
② 마지막 Incremental 반영
③ Source/Target 정합성 확인
④ Application Endpoint 변경
⑤ Target 서비스 시작
순서로 갑니다.
7.36 Cutover 그림
전환 전
Application
│
▼
SOURCE
│
RedisShake
▼
TARGET
최종 동기화
Application Write
STOP
↓
SOURCE = TARGET
전환 후
Application
│
▼
TARGET
입니다.
7.37 Rollback도 생각해야 한다
예를 들어 Target 전환 후 문제가 발생했습니다.
Application
│
▼
Target
❌
이때 단순히 Source로 돌아가면 될 것 같지만 문제는:
Cutover 이후 Target에서 발생한 Write
입니다.
RedisShake는 자동 양방향 Sync가 아니므로:
Target 변경분
→ Source 자동 복귀
❌
입니다.
따라서 Cutover 계획에는 반드시:
Rollback 가능 시간
Write Freeze
Target Write 발생 후 Rollback 방식
을 사전에 정의해야 합니다.
이건 나중 Cutover 단계에서 자세히 다루겠습니다.
7.38 Cluster → Cluster 전체 흐름
지금까지 배운 걸 하나로 합치면:
Application
│
▼
SOURCE CLUSTER
Shard1 Shard2 Shard3
M1 M2 M3
│ │ │
R1 R2 R3
│ │ │
│ Full + Incremental │
▼ ▼ ▼
┌──────────────────┐
│ RedisShake │
│ │
│ Cluster Reader │
│ │
│ Reader1 ← M1 │
│ Reader2 ← M2 │
│ Reader3 ← M3 │
│ │
│ ↓ │
│ Cluster Writer │
└────────┬─────────┘
│
▼
TARGET CLUSTER
Shard1 Shard2 Shard3
M1 M2 M3
│ │ │
R1 R2 R3
RedisShake 내부에서는 Source shard 수에 맞춰 Reader들이 병렬로 동작하고, 처리된 데이터를 Cluster Writer가 Target으로 전달합니다. Tair Open Source
🎯 7단계 핵심 8가지
- Source Cluster의 데이터는 여러 Master에 분산되어 있습니다.
- RedisShake에서 Source는 **cluster=true**입니다.
- RedisShake는 Source Shard별 Reader를 병렬 구성합니다. Tair Open Source
- 각 Reader는 Full RDB + Incremental Stream을 처리합니다. Tair Open Source
- Target도 Cluster면 **redis_writer.cluster=true**입니다. Tair Open Source
- Source Master와 Target Master 수가 반드시 같을 필요는 없습니다.
- RedisShake Pod가 Source/Target 각 Cluster Node 주소에 접근 가능해야 합니다.
- Cutover 판단은 전체가 아니라 Shard별 Lag + 데이터 정합성까지 봐야 합니다.
한 문장으로 압축하면:
Redis Cluster → Redis Cluster Migration은 Source의 각 Master Shard에서 데이터를 병렬로 읽고, RedisShake가 이를 Redis 명령으로 처리한 뒤 Target Cluster의 Hash Slot 구조에 맞춰 다시 분산 저장하는 과정입니다.
그리고 환경에서는 다음 7.1단계가 특히 중요합니다.
운영 K8s Redis Cluster → DR/신규 K8s Redis Cluster에서 Headless Service, Pod IP, cluster-announce-ip/hostname, L4/VIP, 방화벽을 어떻게 설계해야 RedisShake가 각 Master에 실제로 접근할 수 있는지를 네트워크 그림과 함께 보는 단계입니다.
'J-H-T > Redis' 카테고리의 다른 글
| [REDIS-9단계] 서비스 무중단 전환(Cutover) 절차! (0) | 2026.08.18 |
|---|---|
| [REDIS-8단계] 방화벽·포트·네트워크 구성! (0) | 2026.08.17 |
| [REDIS-7.1단계] RedisShake 운영 네트워크 설계! (0) | 2026.08.17 |
| [REDIS-6단계] Master/Replica + Sentinel 환경에서 동기화! (0) | 2026.08.17 |
| [REDIS-5단계] Standalone Redis → Standalone Redis 실습! (0) | 2026.08.16 |
| [REDIS-4.2단계] RedisShake CPU / RAM / Disk 산정! (0) | 2026.08.16 |
| [REDIS-4.1단계] sync_reader를 실제 K8s ConfigMap + Secret + RedisShake Pod + shake.toml 구성 예제! (0) | 2026.08.16 |
| [REDIS-4단계] sync_reader / scan_reader / rdb_reader 차이! (0) | 2026.08.16 |
댓글