本章介紹Redis的一個強大功能--主從複製。一台master主機可以擁有多台slave從機。而一台slave從機又可以擁有多個slave從機。如此下去,形成強大的多層伺服器叢集架構(高擴充)。可以避免Redis單點故障,達到容災復原效果(高可用)。讀寫分離的架構,滿足讀多寫少的並發應用場景。推薦:redis影片教學
主從複製的作用
主從複製,讀寫分離,容災恢復。一台主機負責寫入數據,多台從機負責備份資料。在高並發的場景下,即便是主機掛了,可以用從機取代主機繼續運作,避免單點故障導致系統效能問題。讀寫分離,讓讀多寫少的應用效能更佳。
主從複製架構
At the base of Redis replication there is a very simple to use and configure master-slave replication that allows slave Redis servers to be exact copies of master servers.
確實是簡單的,一個指令: slaveof 主機ip 主機port ,就可以確定主從關係;一個指令:./redis-sentinel sentinel.conf ,就可以開啟哨兵監控。
搭建是簡單的,維護是痛苦的。在高並發場景下,會有很多想不到的問題出現。我們只有清楚複製的原理,熟悉主機,從機宕機後的變化。才能很好的跨過這些坑。下面的每一個步驟都是一個小的知識點,小的場景。每做完一個步驟,你就會收穫到知識。
架構圖:一主二僕一兵(也可以多主多僕多兵)
#搭建前的準備工作
因為窮,筆者選擇用一台伺服器模擬三台主機。和生產環境的差別只是ip位址和port埠不同。
第一步:將redis.conf 拷貝三份,名字分別是,redis6379.conf,redis6380.conf,redis6381.conf
第二步:修改三個檔案的port端口,pid檔名,日誌檔名,rdb檔名
第三步:分別開啟三個視窗模擬三台伺服器,開啟redis服務。
[root@itdragon bin]# cp redis.conf redis6379.conf [root@itdragon bin]# cp redis.conf redis6380.conf [root@itdragon bin]# cp redis.conf redis6381.conf [root@itdragon bin]# vim redis6379.conf logfile "6379.log" dbfilename dump_6379.rdb [root@itdragon bin]# vim redis6380.conf pidfile /var/run/redis_6380.pid port 6380 logfile "6380.log" dbfilename dump_6380.rdb [root@itdragon bin]# vim redis6381.conf port 6381 pidfile /var/run/redis_6381.pid logfile "6381.log" dbfilename dump_6381.rdb [root@itdragon bin]# ./redis-server redis6379.conf [root@itdragon bin]# ./redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> keys * (empty list or set) [root@itdragon bin]# ./redis-server redis6380.conf [root@itdragon bin]# ./redis-cli -h 127.0.0.1 -p 6380 127.0.0.1:6380> keys * (empty list or set) [root@itdragon bin]# ./redis-server redis6381.conf [root@itdragon bin]# ./redis-cli -h 127.0.0.1 -p 6381 127.0.0.1:6381> keys * (empty list or set)
主從複製建置步驟
#基礎建置
第一步:查詢主從複製訊息,分別選擇三個端口,執行命令:info replication。
# 6379 端口 [root@itdragon bin]# ./redis-server redis6379.conf [root@itdragon bin]# ./redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> info replication # Replication role:master connected_slaves:0 ...... # 6380 端口 127.0.0.1:6380> info replication # Replication role:master connected_slaves:0 ...... # 6381 端口 127.0.0.1:6381> info replication # Replication role:master connected_slaves:0 ......
三個連接埠都列印相同的資訊:role:master 角色是master,connected_slaves:0 連接從機數量為零。了解更多參數含義可訪問連接:http://redisdoc.com/server/info.html
第二步:選擇6379端口,執行命令:set k1 v1
127.0.0.1:6379> set k1 v1 OK
第三步:設定主從關係,分別選擇6380端口和6381端口,執行命令:SLAVEOF 127.0.0.1 6379
# 6380 端口 127.0.0.1:6380> SLAVEOF 127.0.0.1 6379 OK 127.0.0.1:6380> info replication # Replication role:slave master_host:127.0.0.1 master_port:6379 ...... # 6381 端口 127.0.0.1:6381> SLAVEOF 127.0.0.1 6379 OK 127.0.0.1:6381> info replication # Replication role:slave master_host:127.0.0.1 master_port:6379 ...... # 6379 端口 127.0.0.1:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=127.0.0.1,port=6380,state=online,offset=98,lag=1 slave1:ip=127.0.0.1,port=6381,state=online,offset=98,lag=1 ......
主從關係發生了變化:
6380端口和6381端口打印的資訊: role:slave 從機;master_host:127.0.0.1 主機的ip位址;master_port:6379 主機的port 連接埠。
6379 連接埠列印的資訊: role:master 主機;connected_slaves:2 連了兩個從機;slaveX : ID、IP 位址、連接埠號碼、連線狀態、從庫資訊
第四步:全量複製,分別選擇6380端口和6381端口,執行命令:get k1
# 6380 端口 127.0.0.1:6380> get k1 "v1" # 6381 端口 127.0.0.1:6381> get k1 "v1"
兩個端口都可以打印k1的值,說明在建立主從關係時,從機便擁有了主機的數據。
第五步:增量複製,選擇6379端口,執行指令:set k2 v2。然後分別選擇6380端口和6381端口,執行指令:get k2
# 6379 端口 127.0.0.1:6379> set k2 v2 OK # 6380 端口 127.0.0.1:6380> get k2 "v2" # 6381 端口 127.0.0.1:6381> get k2 "v2"
兩個端口都可以列印k2的值,說明建立主從關係後,主機新增的資料都會複製給從機。
第六步:主從的讀寫分離,選擇6380端口,執行命令:set k3 v3
# 6380 端口 127.0.0.1:6380> set k3 v3 (error) READONLY You can't write against a read only slave. # 6379 端口 127.0.0.1:6379> set k3 v3 OK
從機6380寫入失敗,是因為讀寫分離的機制。
第七步:主機宕機的情況,選擇6379端口,執行命令:shutdown
# 6379 端口 127.0.0.1:6379> SHUTDOWN not connected> QUIT # 6380 端口 127.0.0.1:6380> info replication # Replication role:slave master_host:127.0.0.1 master_port:6379 ...... # 6381 端口 127.0.0.1:6381> info replication # Replication role:slave master_host:127.0.0.1 master_port:6379 ......
從打印的結果得知:從機原地待命
第八步驟:主機宕機後恢復,選擇6379端口,重啟Redis服務,執行指令:set k4 v4。分別選擇6380端口和6381端口,執行指令:get k4
# 6379 端口 [root@itdragon bin]# ./redis-server redis6379.conf [root@itdragon bin]# ./redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> set k4 v4 OK # 6380 端口 127.0.0.1:6380> get k4 "v4" # 6381 端口 127.0.0.1:6381> get k4 "v4"
主機重啟後,一切正常。
第九步:從機宕機後恢復,選擇6380端口,執行命令:shutdown。選擇6379端口,執行指令:set k5 v5。選擇6380端口,重啟Redis服務後執行命令:get k5
# 6380 端口 127.0.0.1:6380> SHUTDOWN not connected> QUIT [root@itdragon bin]# ./redis-server redis6380.conf [root@itdragon bin]# ./redis-cli -h 127.0.0.1 -p 6380 127.0.0.1:6380> info replication # Replication role:slave master_host:127.0.0.1 master_port:6379 ...... 127.0.0.1:6380> get k5 "v5" # 6379 端口 127.0.0.1:6379> set k5 v5 OK
从机宕机后,一切正常。笔者用的是redis.4.0.2版本的。看过其他教程,从机宕机恢复后,只能同步主机新增数据,也就是k5是没有值的,可是笔者反复试过,均有值。留着备忘!
第十步:去中性化思想,选择6380端口,执行命令:SLAVEOF 127.0.0.1 6381。选择6381端口,执行命令:info replication
# 6380 端口 127.0.0.1:6380> SLAVEOF 127.0.0.1 6381 OK # 6381 端口 127.0.0.1:6381> info replication # Replication role:slave master_host:127.0.0.1 master_port:6379 ...... connected_slaves:1 slave0:ip=127.0.0.1,port=6380,state=online,offset=1677,lag=1 ......
虽然6381 是6380的主机,是6379的从机。在Redis眼中,6381依旧是从机。一台主机配多台从机,一台从机在配多台从机,从而实现了庞大的集群架构。同时也减轻了一台主机的压力,缺点是增加了服务器间的延迟。
从机上位
模拟主机宕机,人为手动怂恿从机上位的场景。先将三个端口恢复成6379是主机,6380和6381是从机的架构。
从机上位步骤:
第一步:模拟主机宕机,选择6379端口,执行命令:shutdown
第二步:断开主从关系,选择6380端口,执行命令:SLAVEOF no one
第三步:重新搭建主从,选择6381端口,执行命令:info replication,SLAVEOF 127.0.0.1 6380
第四步:之前主机恢复,选择6379端口,重启Redis服务,执行命令:info replication
在6379主机宕机后,6380从机断开主从关系,6381开始还在原地待命,后来投靠6380主机后,6379主机回来了当它已是孤寡老人,空头司令。
# 6379端口 127.0.0.1:6379> SHUTDOWN not connected> QUIT # 6380端口 127.0.0.1:6380> SLAVEOF no one OK 127.0.0.1:6380> set k6 v6 OK # 6381端口 127.0.0.1:6381> info replication # Replication role:slave master_host:127.0.0.1 master_port:6379 ...... 127.0.0.1:6381> SLAVEOF 127.0.0.1 6380 OK 127.0.0.1:6381> get k6 "v6"
哨兵监控
从机上位是需要人为控制,在生产环境中是不可取的,不可能有人实时盯着它,也不可能大半夜起床重新搭建主从关系。在这样的需求促使下,哨兵模式来了!!!
哨兵有三大任务:
1 监控:哨兵会不断地检查你的Master和Slave是否运作正常
2 提醒:当被监控的某个Redis出现问题时, 哨兵可以通过API向管理员或者其他应用程序发送通知
3 故障迁移:若一台主机出现问题时,哨兵会自动将该主机下的某一个从机设置为新的主机,并让其他从机和新主机建立主从关系。
哨兵搭建步骤:
第一步:新开一个窗口,取名sentinel,方便观察哨兵日志信息
第二步:创建sentinel.conf文件,也可以从redis的解压文件夹中拷贝一份。
第三步:设置监控的主机和上位的规则,编辑sentinel.conf,输入 sentinel monitor itdragon-redis 127.0.0.1 6379 1 保存退出。解说:指定监控主机的ip地址,port端口,得票数。
第四步:前端启动哨兵,执行命令:./redis-sentinel sentinel.conf。
第五步:模拟主机宕机,选择6379窗口,执行命令:shutdown。
第六步:等待从机投票,在sentinel窗口中查看打印信息。
第七步:启动6379服务器,
语法结构:sentinel monitor 自定义数据库名 主机ip 主机port 得票数
若从机得票数大于设置值,则成为新的主机。若之前的主机恢复后,
如果哨兵也宕机了???那就多配几个哨兵并且相互监控。
# sentinel窗口 [root@itdragon bin]# vim sentinel.conf sentinel monitor itdragon-redis 127.0.0.1 6379 1 [root@itdragon bin]# ./redis-sentinel sentinel.conf ...... 21401:X 29 Nov 15:39:15.052 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ itdragon-redis 127.0.0.1 6380 21401:X 29 Nov 15:39:15.052 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ itdragon-redis 127.0.0.1 6380 21401:X 29 Nov 15:39:45.081 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ itdragon-redis 127.0.0.1 6380 21401:X 29 Nov 16:40:52.055 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ itdragon-redis 127.0.0.1 6380 21401:X 29 Nov 16:41:02.028 * +convert-to-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ itdragon-redis 127.0.0.1 6380 ...... # 6379端口 127.0.0.1:6379> SHUTDOWN not connected> QUIT # 6380端口 127.0.0.1:6380> info replication # Replication role:master connected_slaves:1 slave0:ip=127.0.0.1,port=6381,state=online,offset=72590,lag=0 ...... # 6381端口 127.0.0.1:6381> info replication # Replication role:slave master_host:127.0.0.1 master_port:6380 ......
+slave :一个新的从服务器已经被 Sentinel 识别并关联。
+sdown :给定的实例现在处于主观下线状态。
-sdown :给定的实例已经不再处于主观下线状态。
主从复制的原理
全量复制
实现原理:建立主从关系时,从机会给主机发送sync命令,主机接收命令,后台启动的存盘进程,同时收集所有用于修改命令,传送给从机。
增量复制
实现原理:主机会继续将新收集到的修改命令依次传给从机,实现数据的同步效果。
主从复制的缺点
Redis的主从复制最大的缺点就是延迟,主机负责写,从机负责备份,这个过程有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,从机器数量的增加也会使这个问题更加严重。
總結
1 查看主從複製關係指令:info replication
2 設定主從關係指令:slaveof 主機ip 主機port
# 3 開啟哨兵模式指令:./redis-sentinel sentinel.conf
4 主從複製原則:開始是全量賦值,之後是增量賦值
5 哨兵模式三大任務:監控,提醒,自動故障遷移
更多redis知識請關注redis資料庫教學欄位。
以上是redis主從複製詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!