前言
Master-Slave 是 Redis 提供的主從複製機制,由 Master 負責寫入,並同步數據到所有 Slave
讓 Slave 分擔讀取功能,可減少 Master 負擔
環境
Linux VM = ubuntu-2004-lts
Redis Docker映像檔 = redis:6.0.0
本篇透過 GCP VM 來測試
準備 3 台 Linux VM
1 台 Redis Master
2 台 Redis Slave
機器 | IP |
---|---|
redis-master | 10.140.0.20 |
redis-slave-1 | 10.140.0.21 |
redis-slave-2 | 10.140.0.22 |
設定 VPC & Firewall
# 建立 VPC
gcloud compute networks create redis-vpc --subnet-mode custom
# 建立 VPC 子網路
gcloud compute networks subnets create redis-vpc-subnet \
--network redis-vpc \
--range 10.240.0.0/24 \
--region asia-east1
# 設定機器對內防火牆
gcloud compute firewall-rules create redis-vpc-allow-internal \
--allow tcp,udp,icmp,ipip \
--network redis-vpc \
--source-ranges 10.240.0.0/24
# 設定機器對外防火牆 (IP 請指定要訪問 Redis 的 連線IP)
gcloud compute firewall-rules create redis-vpc-allow-external \
--allow tcp:6379 \
--network redis-vpc \
--source-ranges x.x.x.x
# 設定機器對外防火牆 SSH 連線
gcloud compute firewall-rules create redis-vpc-allow-ssh \
--allow tcp:22 \
--network redis-vpc \
--source-ranges 0.0.0.0/0
設定 VM
建立 Master 機器
gcloud compute instances create redis-master \
--async \
--boot-disk-size 100GB \
--can-ip-forward \
--image-family ubuntu-2004-lts \
--image-project ubuntu-os-cloud \
--machine-type e2-standard-2 \
--private-network-ip 10.240.0.20 \
--scopes compute-rw,storage-ro,service-management,service-control,logging-write,monitoring \
--subnet redis-vpc-subnet \
--zone asia-east1-a \
--tags redis-vpc
建立 2 台 Slave 機器
for i in 1 2; do
gcloud compute instances create redis-slave-${i} \
--async \
--boot-disk-size 100GB \
--can-ip-forward \
--image-family ubuntu-2004-lts \
--image-project ubuntu-os-cloud \
--machine-type e2-standard-2 \
--private-network-ip 10.240.0.2${i} \
--scopes compute-rw,storage-ro,service-management,service-control,logging-write,monitoring \
--subnet redis-vpc-subnet \
--zone asia-east1-a \
--tags redis-vpc
done
安裝 Docker
參考 w4560000 - Linux 安裝 Docker、Docker-Compose
3 台 VM 都先設定好 volumn 資料夾
mkdir redis && mkdir redisdata
Redis Master-Slave 建置
Redis Slave 服務啟動後,初始連線到 Master 時,Master 會執行 Bgsave 建立 RDB 檔並回傳給 Slave 來載入資料
redis.conf
repl-ping-replica-period
master 每隔幾秒會 ping slave,確認是否活著
ex: repl-ping-replica-period 10 (預設)repl-timeout
當 redis 檢測到 repl-timeout 超時,將會關閉主從連線,並由 slave 重新發起主從連線請求
該值需大於 repl-ping-replica-period,避免一直觸發 timeout 重連
以下三種狀況是超時狀況- slave 角度,master 同步 RDB 數據超時
- slave 角度,在 repl-timeout 時間內沒有收到 master 的發送的數據或 ping
- master 角度,在 repl-timeout 時間內沒有收到 slave 發送的 REPLCONF ACK
ex: repl-timeout 60 (預設)
Master、Slave 都先新增 redis.conf
路徑 ~/redis/redis.conf
bind 0.0.0.0
protected-mode no
dir ./
# AOF
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
# AOF rewrite
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 0
auto-aof-rewrite-min-size 1mb
aof-load-truncated no
aof-use-rdb-preamble yes
# REPLICATION
repl-ping-replica-period 10
repl-timeout 60
Master 建立 Redis 服務
docker run --name redis-master \
-p 6379:6379 \
-v /home/leozheng0411/redis:/usr/local/etc/redis \
-v /home/leozheng0411/redisdata:/data \
-d redis:6.0.0 \
redis-server /usr/local/etc/redis/redis.conf
Slave 建立 Redis 服務
docker run --name redis-slave \
-p 6379:6379 \
-v /home/leozheng0411/redis:/usr/local/etc/redis \
-v /home/leozheng0411/redisdata:/data \
-d redis:6.0.0 \
redis-server /usr/local/etc/redis/redis.conf --replicaof 10.240.0.20 6379
備註: 雖然 Slave 在這邊主要是讀取功能,不負責寫入,並且是接收 Master 同步過來的資料
理論上不需要在多做 AOF 來備份,但若 Master 發生異常,Slave 則會升為 Master,則此時若沒有備份機制,那就很危險了
所以 Slave 建置時,一樣先建好備份機制,以防萬一
確認是否有主從同步
Master
# 查看 Replication 資訊
docker exec -it redis-master redis-cli info replication
# 輸出
role:master
connected_slaves:2
slave0:ip=10.240.0.21,port=6379,state=online,offset=1469,lag=0
slave1:ip=10.240.0.22,port=6379,state=online,offset=1469,lag=0
master_replid:5ab3de3667aafae90f3d12900834098fa01c65c1
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1469
master_repl_meaningful_offset:853
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1469
# 設定資料測試
docker exec -it redis-master redis-cli SET Key1 "1"
# 輸出
OK
Slave1
docker exec -it redis-slave redis-cli GET Key1
# 輸出
"1"
Slave2
docker exec -it redis-slave redis-cli GET Key1
# 輸出
"1"
Slave 是否可寫入資料
Slave1
docker exec -it redis-slave redis-cli SET Key1 "10"
# 輸出
(error) READONLY You can't write against a read only replica.
因主要是由 Master 寫入資料,同步到 Slave,其他應用程式可讀取 Slave,來達成讀寫分離
所以 Redis 預設 Slave 是不能寫入資料
但仍可以設定讓 Slave 可以寫入
docker exec -it redis-slave redis-cli CONFIG SET slave-read-only no
# 輸出
OK
docker exec -it redis-slave redis-cli SET Key1 "10"
# 輸出
OK
但這個操作只有 Slave1 有影響,並不會同步到 Master、Slave2
會造成主從資料不一致,若無特殊情境的話,則讓 Slave 保持僅有讀的權限就好,避免資料異常
參考文件
HackMD tienyulin - Redis (六) - 主從複製、哨兵與叢集模式#主從複製模式
轉載請註明來源,若有任何錯誤或表達不清楚的地方,歡迎在下方評論區留言,也可以來信至 leozheng0621@gmail.com
如果文章對您有幫助,歡迎斗內(donate),請我喝杯咖啡