文章目錄
- 前言
- 技術積累
- 1、Redis 主從復制機制
- 2、Docker Compose 編排
- 3、 Redis 配置文件定制
- 4、 驗證主從狀態
- 5、 自動化部署與維護
- 環境準備
- 實戰演示
- 創建redis目錄及配置
- 1、創建redis目錄
- 2、創建redis配置文件
- 啟動redis集群服務
- 1、創建docker-compose編排文件
- 2、編排docker-compose
- 驗證Redis集群主從復制
- Redis集群數據持久化驗證
- 總結
前言
隨著互聯網應用的快速發展,高并發訪問和數據緩存的需求日益增長。Redis 作為一款高性能的內存數據庫,廣泛應用于緩存、消息隊列、分布式鎖等場景。為了提升 Redis 的可用性和讀寫性能,通常采用主從復制架構來實現讀寫分離。本次實戰通過 Docker Compose 快速搭建一個 Redis 主從復制集群,模擬生產環境中 Redis 高可用架構的基礎部署方式。通過該實踐,可以更好地理解 Redis 主從復制機制、Docker 容器編排以及服務間通信原理。
技術積累
1、Redis 主從復制機制
- Redis 主從復制是異步復制,默認情況下從節點連接到主節點后會進行一次全量同步(RDB dump),之后進行增量同步(AOF 或 repl-backlog)。
- 從節點可處理讀請求,減輕主節點壓力,適用于讀多寫少的場景。
- 支持鏈式復制,即從節點也可以作為其他從節點的主節點。
- 普通主從集群沒有自動故障轉移,這個是最大的缺點
2、Docker Compose 編排
- 使用 docker-compose.yml 文件定義多個容器服務,實現 Redis 主從節點的快速部署。
- 通過自定義網絡(networks)確保容器間可通過服務名互相訪問。
- 可掛載本地目錄作為配置文件或持久化存儲,便于調試和數據保留。
3、 Redis 配置文件定制
- 在從節點配置中添加 replicaof 指令,指定其主節點地址。
- 可設置只讀模式(slave-read-only yes)、連接超時時間、密碼認證等安全策略。
4、 驗證主從狀態
- 進入 Redis 容器執行 redis-cli info replication 查看主從狀態信息。
- 主節點顯示連接的從節點數量,從節點顯示其所屬主節點的信息。
5、 自動化部署與維護
- 利用 Docker 的健康檢查功能(healthcheck)監控 Redis 狀態。
- 通過 shell 腳本或 CI/CD 工具實現一鍵部署與擴容。
環境準備
- 安裝 docker
- 安裝 docker compose
實戰演示
本地演示使用windows11 docker desktop 環境,有條件的可以使用Linux自動安裝docker環境。
創建redis目錄及配置
1、創建redis目錄
主從集群目錄結構如下所示:
- master-slave
- redis-master
- data
- conf
- redis.conf
- redis-slave1
- data
- conf
- redis.conf
- redis-slave2
- data
- conf
- redis.conf
- docker-compose.yaml
- redis-master
2、創建redis配置文件
- master 主節點: redis.conf
# 主節點配置
# 綁定的主機地址
bind 0.0.0.0
# 允許外網訪問
protected-mode no
# 啟用守護進程后,Redis會把pid寫到一個pidfile中,在/var/run/redis.pid
daemonize no
# 當Redis以守護進程方式運行時,Redis默認會把pid寫入/var/run/redis.pid文件,可以通過pidfile指定
pidfile /var/run/redis.pid
# 指定Redis監聽端口,默認端口為6379
# 如果指定0端口,表示Redis不監聽TCP連接
port 6379
# 當客戶端閑置多長時間后關閉連接,如果指定為0,表示關閉該功能
timeout 0
# 指定日志記錄級別,Redis總共支持四個級別:debug、verbose、notice、warning,默認為verbose
# debug (很多信息, 對開發/測試比較有用)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel verbose
# 日志記錄方式,默認為標準輸出,如果配置為redis為守護進程方式運行,而這里又配置為標準輸出,則日志將會發送給/dev/null
logfile redis.log################################ SNAPSHOTTING #################################
# RDB存儲配置
# 指定在多長時間內,有多少次更新操作,就將數據同步到數據文件,可以多個條件配合
# Save the DB on disk:
#
# save <seconds> <changes>
#
# Will save the DB if both the given number of seconds and the given
# number of write operations against the DB occurred.
#
# 滿足以下條件將會同步數據:
# 900秒(15分鐘)內有1個更改
# 300秒(5分鐘)內有10個更改
# 60秒內有10000個更改
# Note: 可以把所有“save”行注釋掉,這樣就取消同步操作了
save 900 1
save 300 10
save 60 10000
# 指定存儲至本地數據庫時是否壓縮數據,默認為yes,Redis采用LZF壓縮,如果為了節省CPU時間,可以關閉該選項,但會導致數據庫文件變的巨大
rdbcompression yes
# 指定本地數據庫文件名,默認值為dump.rdb
dbfilename dump.rdb
# 指定本地數據庫存放目錄,文件名由上一個dbfilename配置項指定
dir /data################################# REPLICATION ################################################################### SECURITY ###################################
# 設置密碼
requirepass 123456789############################## APPEND ONLY MODE ###############################
# 開啟aof配置
appendonly yes
# 指定更新日志條件,共有3個可選值:
# no:表示等操作系統進行數據緩存同步到磁盤(快)
# always:表示每次更新操作后手動調用fsync()將數據寫到磁盤(慢,安全)
# everysec:表示每秒同步一次(折衷,默認值)
appendfsync everysec
# 指定更新日志文件名,默認為appendonly.aof
appendfilename "appendonly.aof"
- slave1 從節點1 : redis.conf
# 從節點配置
# 綁定的主機地址
bind 0.0.0.0
# 允許外網訪問
protected-mode no
# 啟用守護進程后,Redis會把pid寫到一個pidfile中,在/var/run/redis.pid
daemonize no
# 當Redis以守護進程方式運行時,Redis默認會把pid寫入/var/run/redis.pid文件,可以通過pidfile指定
pidfile /var/run/redis.pid
# 指定Redis監聽端口,默認端口為6379
# 如果指定0端口,表示Redis不監聽TCP連接
port 6379
# 當客戶端閑置多長時間后關閉連接,如果指定為0,表示關閉該功能
timeout 0
# 指定日志記錄級別,Redis總共支持四個級別:debug、verbose、notice、warning,默認為verbose
# debug (很多信息, 對開發/測試比較有用)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel verbose
# 日志記錄方式,默認為標準輸出,如果配置為redis為守護進程方式運行,而這里又配置為標準輸出,則日志將會發送給/dev/null
logfile redis.log################################ SNAPSHOTTING #################################
# RDB存儲配置
# 指定在多長時間內,有多少次更新操作,就將數據同步到數據文件,可以多個條件配合
# Save the DB on disk:
#
# save <seconds> <changes>
#
# Will save the DB if both the given number of seconds and the given
# number of write operations against the DB occurred.
#
# 滿足以下條件將會同步數據:
# 900秒(15分鐘)內有1個更改
# 300秒(5分鐘)內有10個更改
# 60秒內有10000個更改
# Note: 可以把所有“save”行注釋掉,這樣就取消同步操作了
save 900 1
save 300 10
save 60 10000
# 指定存儲至本地數據庫時是否壓縮數據,默認為yes,Redis采用LZF壓縮,如果為了節省CPU時間,可以關閉該選項,但會導致數據庫文件變的巨大
rdbcompression yes
# 指定本地數據庫文件名,默認值為dump.rdb
dbfilename dump.rdb
# 指定本地數據庫存放目錄,文件名由上一個dbfilename配置項指定
dir /data################################# REPLICATION #################################
# 設置當本機為slav服務時,設置master服務的ip地址及端口,在Redis啟動時,它會自動從master進行數據同步
replicaof redis-master 6379
# 開啟只讀模式
replica-read-only yes
# 當master服務設置了密碼保護時,slav服務連接master的密碼
masterauth 123456789repl-diskless-load on-empty-db################################## SECURITY ###################################
# 設置密碼
requirepass 123456789############################## APPEND ONLY MODE ###############################
# 開啟aof配置
appendonly yes
# 指定更新日志條件,共有3個可選值:
# no:表示等操作系統進行數據緩存同步到磁盤(快)
# always:表示每次更新操作后手動調用fsync()將數據寫到磁盤(慢,安全)
# everysec:表示每秒同步一次(折衷,默認值)
appendfsync everysec
# 指定更新日志文件名,默認為appendonly.aof
appendfilename "appendonly.aof"
- slave2 從節點2: redis.conf和 slave1 從節點1 配置一致,復制一份即可。
啟動redis集群服務
1、創建docker-compose編排文件
- 創建 docker-compose.yaml
version: '3.8'services:redis-master:image: redis:6-alpinecontainer_name: redis-masterenvironment:- "TZ=Asia/Shanghai"ports:- "6377:6379"volumes:- ./redis-master/conf/redis.conf:/usr/local/etc/redis/redis.conf- ./redis-master/data:/datacommand: redis-server /usr/local/etc/redis/redis.confnetworks:- redis-master-slaveredis-slave1:image: redis:6-alpinecontainer_name: redis-slave1environment:- "TZ=Asia/Shanghai"ports:- "6380:6379"volumes:- ./redis-slave1/conf/redis.conf:/usr/local/etc/redis/redis.conf- ./redis-slave1/data:/datacommand: redis-server /usr/local/etc/redis/redis.confdepends_on:- redis-masternetworks:- redis-master-slaveredis-slave2:image: redis:6-alpinecontainer_name: redis-slave2environment:- "TZ=Asia/Shanghai"ports:- "6381:6379"volumes:- ./redis-slave2/conf/redis.conf:/usr/local/etc/redis/redis.conf- ./redis-slave2/data:/datacommand: redis-server /usr/local/etc/redis/redis.confdepends_on:- redis-masternetworks:- redis-master-slavenetworks:redis-master-slave:driver: bridge
2、編排docker-compose
- 運行 docker-compose.yaml
docker-compose -f docker-compose.yaml up -d
- 查看redis集群容器
docker ps -a
驗證Redis集群主從復制
- 檢查主節點信息
docker exec -it redis-master redis-cli -h 127.0.0.1 -p 6379 -a 123456789 info replication
執行上述命令,得到以下輸出:role表示角色,connected_slaves表示副本數
# Replication
role:master
connected_slaves:2
slave0:ip=172.20.0.3,port=6379,state=online,offset=603741,lag=0
slave1:ip=172.20.0.4,port=6379,state=online,offset=603741,lag=0
master_failover_state:no-failover
master_replid:149762551ed827fe20934a1917ba22acffdd96f2
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:603741
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:603741
- 檢查從節點1信息
docker exec -it redis-slave1 redis-cli -h 127.0.0.1 -p 6379 -a 123456789 info replication
執行上述命令,得到以下輸出:role表示角色,master_link_status表示是否連接成功,up表示成功,down表示失敗
# Replication
role:slave
master_host:redis-master
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_read_repl_offset:603811
slave_repl_offset:603811
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:149762551ed827fe20934a1917ba22acffdd96f2
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:603811
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:603811
- 檢查從節點2信息
docker exec -it redis-slave2 redis-cli -h 127.0.0.1 -p 6379 -a 123456789 info replication
執行上述命令,得到以下輸出:role表示角色,master_link_status表示是否連接成功,up表示成功,down表示失敗
# Replication
role:slave
master_host:redis-master
master_port:6379
master_link_status:up
master_last_io_seconds_ago:8
master_sync_in_progress:0
slave_read_repl_offset:603853
slave_repl_offset:603853
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:149762551ed827fe20934a1917ba22acffdd96f2
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:603853
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:603853
Redis集群數據持久化驗證
- 寫入數據到主節點
docker exec -it redis-master redis-cli -h 127.0.0.1 -p 6379 -a 123456789 SET name "test_senfel_data"
- 主節點讀取數據查看是否設置成功
docker exec -it redis-master redis-cli -h 127.0.0.1 -p 6379 -a 123456789 GET name
- 從節點1讀取數據,查看是否同步
docker exec -it redis-slave1 redis-cli -h 127.0.0.1 -p 6379 -a 123456789 GET name
- 從節點2讀取數據,查看是否同步
docker exec -it redis-slave2 redis-cli -h 127.0.0.1 -p 6379 -a 123456789 GET name
PS C:\Users\user> docker exec -it redis-master redis-cli -h 127.0.0.1 -p 6379 -a 123456789 SET name "test_senfel_data"
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
OK
PS C:\Users\user> docker exec -it redis-master redis-cli -h 127.0.0.1 -p 6379 -a 123456789 GET name
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
"test_senfel_data"
PS C:\Users\user> docker exec -it redis-slave1 redis-cli -h 127.0.0.1 -p 6379 -a 123456789 GET name
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
"test_senfel_data"
PS C:\Users\user> docker exec -it redis-slave2 redis-cli -h 127.0.0.1 -p 6379 -a 123456789 GET name
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
"test_senfel_data"
總結
本次實戰成功利用 Docker Compose 搭建了一個 Redis 主從復制環境,可以掌握Redis 主從復制的基本原理與配置方法,Docker Compose 多服務容器編排的能力,以及Redis 服務的容器化部署與管理。但是普通主從復制雖然可以提升讀性能和數據冗余功能,卻不能實現高可用的,因為它并沒有實現自動故障轉移。故下一期我們將繼續實戰可自動故障轉移的哨兵模式,敬請鑒賞。