筆者目前所在公司存在多套 Redis 叢集:
上雲後,均為廣東的某個雲廠商的 2 個可用區,不再使用 IDC 資料中心,部署架構一致。
有人提出了一個很耐人尋味的問題:
這個架構有問題,如果兩地之間網路故障,必定會出現腦裂!
真的會出現腦裂嗎?
不至於吧!網路分割區後,理論上廣州機房是可用的,中山因為沒有主(存取從庫將槽位重定向回主庫),所以中山機房不可用。所以只有一個機房可寫,不會腦裂。
猜想終究是猜想,實踐出真知!現在 docker 太方便了,搭一個叢集模擬一下就 OK 了~
準備環境:
建立以下資料夾,並準備 docker-compose.yml:
mkdir -p ./data/redis/8001/data && \
mkdir -p ./data/redis/8002/data && \
mkdir -p ./data/redis/8003/data && \
mkdir -p ./data/redis/8004/data && \
mkdir -p ./data/redis/8005/data && \
mkdir -p ./data/redis/8006/data && \
mkdir -p ./data/redis/9001/data && \
mkdir -p ./data/redis/9002/data && \
mkdir -p ./data/redis/9003/data && \
mkdir -p ./data/redis/9004/data && \
mkdir -p ./data/redis/9005/data && \
mkdir -p ./data/redis/9006/data
廣州機房 6 個埠:
version: '3'
services:
redis_gz_1:
image: publicisworldwide/redis-cluster
network_mode: host
volumes:
- ./data/redis/8001/data:/data
environment:
- REDIS_PORT=8001
redis_gz_2:
image: publicisworldwide/redis-cluster
network_mode: host
volumes:
- ./data/redis/8002/data:/data
environment:
- REDIS_PORT=8002
redis_gz_3:
image: publicisworldwide/redis-cluster
network_mode: host
volumes:
- ./data/redis/8003/data:/data
environment:
- REDIS_PORT=8003
redis_gz_4:
image: publicisworldwide/redis-cluster
network_mode: host
volumes:
- ./data/redis/8004/data:/data
environment:
- REDIS_PORT=8004
redis_gz_5:
image: publicisworldwide/redis-cluster
network_mode: host
volumes:
- ./data/redis/8005/data:/data
environment:
- REDIS_PORT=8005
redis_gz_6:
image: publicisworldwide/redis-cluster
network_mode: host
volumes:
- ./data/redis/8006/data:/data
environment:
- REDIS_PORT=8006
中山機房 6 個埠:
version: '3'
services:
redis_zs_1:
image: publicisworldwide/redis-cluster
network_mode: host
volumes:
- ./data/redis/9001/data:/data
environment:
- REDIS_PORT=9001
redis_zs_2:
image: publicisworldwide/redis-cluster
network_mode: host
volumes:
- ./data/redis/9002/data:/data
environment:
- REDIS_PORT=9002
redis_zs_3:
image: publicisworldwide/redis-cluster
network_mode: host
volumes:
- ./data/redis/9003/data:/data
environment:
- REDIS_PORT=9003
redis_zs_4:
image: publicisworldwide/redis-cluster
network_mode: host
volumes:
- ./data/redis/9004/data:/data
environment:
- REDIS_PORT=9004
redis_zs_5:
image: publicisworldwide/redis-cluster
network_mode: host
volumes:
- ./data/redis/9005/data:/data
environment:
- REDIS_PORT=9005
redis_zs_6:
image: publicisworldwide/redis-cluster
network_mode: host
volumes:
- ./data/redis/9006/data:/data
environment:
- REDIS_PORT=9006
docker-compose up 啟動後,使用以下命令搭建叢集:
docker run --rm -it inem0o/redis-trib create --replicas 1 \
10.43.2.6:8001 \
10.43.2.6:8002 \
10.43.2.6:8003 \
10.43.2.6:8004 \
10.43.3.7:9004 \
10.43.2.6:8005 \
10.43.3.7:9005 \
10.43.2.6:8006 \
10.43.3.7:9006 \
10.43.3.7:9001 \
10.43.3.7:9002 \
10.43.3.7:9003
你會發現叢集搭起來了!有以下提示資訊:
...master:
10.43.2.6:8001
10.43.3.7:9004
10.43.2.6:8002
10.43.3.7:9005
10.43.2.6:8003
10.43.3.7:9006
...
Adding replica 10.43.3.7:9001 to 10.43.2.6:8001
Adding replica 10.43.2.6:8004 to 10.43.3.7:9004
Adding replica 10.43.3.7:9002 to 10.43.2.6:8002
Adding replica 10.43.2.6:8005 to 10.43.3.7:9005
Adding replica 10.43.3.7:9003 to 10.43.2.6:8003
Adding replica 10.43.2.6:8006 to 10.43.3.7:9006
...
此時,叢集是 廣州、中山 各 3 個 master,不符合我們的場景,需要手工切換一下主從:
# 分別在從庫 3 個埠做主從切換 10.43.2.6:9004-9006
redis-cli -h 10.43.2.6 -p 8004 CLUSTER FAILOVER
OK
redis-cli -h 10.43.2.6 -p 8005 CLUSTER FAILOVER
OK
redis-cli -h 10.43.2.6 -p 8006 CLUSTER FAILOVER
OK
3 個埠提主成功,10.43.2.6 此時執行 6 個 master,而 10.43.3.7 執行 6 個 slave 範例。
如何斷網?很簡單,iptables 無敵!
我們在廣州(10.43.2.6)丟掉中山(10.43.3.7)的包就好了:
iptables -I INPUT -s 10.43.3.7 -pudp --dport 18001:18006 -j DROP && \
iptables -I INPUT -s 10.43.3.7 -ptcp --dport 18001:18006 -j DROP && \
iptables -I INPUT -s 10.43.3.7 -ptcp --dport 8001:8006 -j DROP && \
iptables -I INPUT -s 10.43.3.7 -pudp --dport 8001:8006 -j DROP
執行後,中山一直列印重連主庫失敗的紀錄檔,主庫也探測到從庫斷開了,通過 CLUSTER NODES 命令可以獲取各個節點狀態。
結論一:A [6Master/0Slave] + B [0Master/6Slave],A 機房可讀可寫,B 機房不可讀不可寫(CLUSTERDOWN)
報錯資訊如下:
10.43.3.7:9006> set a12 2
(error) CLUSTERDOWN The cluster is down
另外,我還測試了主庫分佈在雙機房的情況:
結論二:A [4Master/2Slave] + B [2Master/4Slave],A 機房可讀可寫,B 機房不可讀不可寫(CLUSTERDOWN)
結論三:A [3Master/3Slave] + B [3Master/3Slave],AB 機房均不可讀不可寫(CLUSTERDOWN)
為什麼不可讀?
因為請求從庫它會自動轉發(MOVED)到主庫,而主庫不可用(達不到半數以上節點),所以徹底涼了!
解決辦法是不使用偶數節點,極端情況下(master 均等分佈兩地)會導致整個叢集不可用。
實驗完,不要忘了刪掉規則,恢復網路:
iptables -D INPUT -s 10.43.3.7 -pudp --dport 18001:18006 -j DROP && \
iptables -D INPUT -s 10.43.3.7 -ptcp --dport 18001:18006 -j DROP && \
iptables -D INPUT -s 10.43.3.7 -ptcp --dport 8001:8006 -j DROP && \
iptables -D INPUT -s 10.43.3.7 -pudp --dport 8001:8006 -j DROP
(完)
文章來源於本人部落格,釋出於 2022-03-12,原文連結:https://imlht.com/archives/254/