🌐 Redis 分散式架構:主從複製、哨兵、Cluster
📌 單機 Redis 的限制
| 問題 | 說明 |
|---|---|
| 單點故障 | Redis 掛了,整個快取失效 |
| 容量限制 | 受限於單機記憶體 |
| 效能瓶頸 | 讀寫都在同一台 |
解決方案:分散式架構。
📌 主從複製(Replication)
寫入請求 → Master(主節點)
↓ 自動同步
讀取請求 → Slave 1(從節點)
讀取請求 → Slave 2(從節點)
設定方式
# slave 的 redis.conf
replicaof 192.168.1.100 6379
# 或在 Redis CLI 中動態設定
REPLICAOF 192.168.1.100 6379
# 查看複製資訊
INFO replication
Docker Compose 範例
version: '3.8'
services:
redis-master:
image: redis:latest
ports:
- "6379:6379"
redis-slave-1:
image: redis:latest
ports:
- "6380:6379"
command: redis-server --replicaof redis-master 6379
redis-slave-2:
image: redis:latest
ports:
- "6381:6379"
command: redis-server --replicaof redis-master 6379
.NET 讀寫分離
// 連線字串指定多個節點
var config = ConfigurationOptions.Parse(
"master:6379,slave1:6380,slave2:6381");
var redis = ConnectionMultiplexer.Connect(config);
// 讀取:自動走 Slave
var db = redis.GetDatabase();
var value = await db.StringGetAsync("key",
CommandFlags.PreferReplica);
// 寫入:一定走 Master
await db.StringSetAsync("key", "value");
📌 Redis Sentinel(哨兵)
主從複製的問題:Master 掛了怎麼辦? → Sentinel 自動故障轉移!
Sentinel 1 ──┐
Sentinel 2 ──┼── 監控 Master + Slaves
Sentinel 3 ──┘ ↓
Master 掛了!
↓
Sentinel 投票選新 Master
↓
Slave 1 升級為 Master
Slave 2 指向新 Master
設定方式
# sentinel.conf
sentinel monitor mymaster 192.168.1.100 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
.NET 連接 Sentinel
var config = new ConfigurationOptions
{
ServiceName = "mymaster",
CommandMap = CommandMap.Sentinel
};
config.EndPoints.Add("sentinel1:26379");
config.EndPoints.Add("sentinel2:26379");
config.EndPoints.Add("sentinel3:26379");
var redis = ConnectionMultiplexer.Connect(config);
// 自動連接到 Master,故障轉移時自動切換
📌 Redis Cluster
當資料量超過單機記憶體時,需要 分片(Sharding)。
Redis Cluster 共有 16384 個 Slot
Node A: Slot 0 ~ 5460
Node B: Slot 5461 ~ 10922
Node C: Slot 10923 ~ 16383
key "user:1001" → CRC16("user:1001") % 16384 → Slot 8732 → Node B
key "user:2001" → CRC16("user:2001") % 16384 → Slot 3291 → Node A
特點
- 資料自動分片到多個節點
- 每個 Master 有 Slave 備援
- 客戶端透過 MOVED 重導向找到正確節點
- 最少 3 個 Master + 3 個 Slave = 6 個節點
Docker Compose 搭建
version: '3.8'
services:
redis-1:
image: redis:latest
command: >
redis-server
--cluster-enabled yes
--cluster-config-file nodes.conf
--cluster-node-timeout 5000
--port 7001
ports:
- "7001:7001"
redis-2:
image: redis:latest
command: >
redis-server
--cluster-enabled yes
--cluster-config-file nodes.conf
--cluster-node-timeout 5000
--port 7002
ports:
- "7002:7002"
redis-3:
image: redis:latest
command: >
redis-server
--cluster-enabled yes
--cluster-config-file nodes.conf
--cluster-node-timeout 5000
--port 7003
ports:
- "7003:7003"
# 建立 Cluster
redis-cli --cluster create \
redis-1:7001 redis-2:7002 redis-3:7003 \
--cluster-replicas 0
.NET 連接 Cluster
var config = ConfigurationOptions.Parse(
"node1:7001,node2:7002,node3:7003");
var redis = ConnectionMultiplexer.Connect(config);
// 操作方式完全相同,StackExchange.Redis 自動處理重導向
var db = redis.GetDatabase();
await db.StringSetAsync("key", "value");
📌 一致性雜湊(Consistent Hashing)
Redis Cluster 使用 CRC16 + Slot 分片。但了解一致性雜湊的概念很重要:
傳統雜湊:hash(key) % N
→ 增減節點時,幾乎所有 key 都要重新分配
一致性雜湊:hash(key) 映射到環上
→ 增減節點只影響相鄰的一小段
→ 大幅減少資料遷移量
📌 架構選擇指南
| 架構 | 適用場景 | 節點數 |
|---|---|---|
| 單機 | 開發/測試 | 1 |
| 主從 | 讀多寫少,需讀寫分離 | 1 Master + N Slave |
| Sentinel | 需要高可用(自動故障轉移) | 3 Sentinel + 主從 |
| Cluster | 大資料量 + 高可用 | 至少 6 (3M + 3S) |
🔑 重點整理
- 主從複製 解決讀取效能,但無法自動故障轉移
- Sentinel 監控主從,Master 掛了自動選新 Master
- Cluster 將資料分片到多個節點,解決容量問題
- StackExchange.Redis 自動處理 Cluster 重導向
- 生產環境至少用 Sentinel,大規模用 Cluster