Redis 主從複製、哨兵模式、Cluster叢集
一、Redis主從複製
1.1、什麼是主從複製
如圖:
將一臺Redis伺服器的資料,複製到其他的Redis伺服器。前者稱為主節點(master),後者稱為從節點(slave),資料的複製是單向的,只能由主節點到從節點。預設情況下,每臺Redis伺服器都是主節點,且一個主節點可以有多個從節點(或沒有從節點),但一個從節點只能有一個主節點。
- 簡單的說就是主機資料更新後根據配置和策略, 自動同步到備機的master/slaver機制,Master以寫為主,Slave以讀為主。
1.2、主從複製的作用
- 一個是讀寫分離,分擔 "master" 的讀寫壓力
- 一個是方便做容災恢復
除了上述作用以外,主從複製還是哨兵和叢集能夠實施的基礎,因此說主從複製是Redis高可用的基礎。
1.3、主從複製流程
(1)若啟動一個Slave機器程序,則它會向Master機器傳送一個"sync command"命令,請求同步連線
(2)無論是第一次連線還是重新連線,Master機器都會啟動一個後臺程序,將資料快照儲存到資料檔案中(執行rdb操作),同時Master還會記錄修改資料的所有命令並快取在資料檔案中
(3)後臺程序完成快取操作之後,Master機器就會向Slave機器傳送資料檔案,slave端機器將資料檔案儲存到硬碟上,然後將其載入到記憶體中,接著Master機器就會將修改資料的所有操作一併傳送給Slav端機器。若Slave出現故障導致宕機,則恢復正常後會自動重新連線
(4)Master機器收到Slave端機器的連線後,將其完整的資料檔案傳送給Slave端機器,如果Mater同時收到多個slave發來的同步請求,則Master會在後臺啟動一個程序以儲存資料檔案,然後將其傳送給所有的Slave端機器,確保所有的slave端機器都正常
1.4、主從複製的優缺點
優點:
- 避免單點故障,將資料庫複製多個副本以部署在不同的伺服器上,這樣即使有一臺伺服器出現故障,其他伺服器依然可以繼續提供服務。
- master能自動將資料同步到slave,可以進行讀寫分離,分擔master的讀壓力
- master、slave之間的同步是以非阻塞的方式進行的,同步期間,客戶端仍然可以提交查詢或更新請求
缺點:
- 不具備自動容錯與恢復功能,master或slave的宕機都可能導致客戶端請求失敗,需要等待機器重啟或手動切換客戶端IP才能恢復
- master宕機,如果宕機前資料沒有同步完,則切換IP後會存在資料不一致的問題
- 難以支援線上擴容,Redis的容量受限於單機配置
二、Redis哨兵模式
2.1、什麼是哨兵模式?
第一種主從同步/複製的模式,當主伺服器宕機後,需要手動把一臺從伺服器切換為主伺服器,這就需要人工干預,費事費力,還會造成一段時間內服務不可用。這不是一種推薦的方式,更多時候,我們優先考慮哨兵模式。哨兵模式是一種特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一個獨立的程序,作為程序,它會獨立執行。其原理是哨兵通過傳送命令,等待Redis伺服器響應,從而監控運行的多個 Redis 例項。
2.2、哨兵模式的作用
1)通過傳送命令,讓 Redis 伺服器返回監控其執行狀態,包括主伺服器和從伺服器;
2)當哨兵監測到 master 宕機,會自動將 slave 切換成 master ,然後通過釋出訂閱模式通知其他的從伺服器,修改配置檔案,讓它們切換主機。
3)哨兵可以將故障轉移的結果傳送給客戶端
2.3、多哨兵模式
然而一個哨兵程序對Redis伺服器進行監控,也可能會出現問題,為此,我們可以使用多個哨兵進行監控。各個哨兵之間還會進行監控,這樣就形成了多哨兵模式。
2.4、哨兵的工作模式
(1)所有哨兵都會監控節點,哨兵之間會共享伺服器的狀態資料,對整個叢集實現監控
(2)哨兵的啟動依賴於主從模式,所以須把主從模式安裝好的情況下再去做哨兵模式,所有節點上都需要部署哨兵模式,哨兵模式會監控所有的 Redis 工作節點是否正常,當Master出現問題的時候,
因為其他節點與主節點失去聯絡,因此會投票,投票過半就認為這個Master的確出現問題,然後會通知哨兵間,然後從Slaves中選取一個作為新的Master
(3)需要特別注意的是,客觀下線是主節點才有的概念,如果從節點和哨兵節點發生故障,被哨兵主觀下線後,不會再有後續的客觀下線和故障轉移操作
主觀下線:當某個哨兵認為節點宕機,是主觀下線
客觀下線:當所有哨兵投票後票數過半後確認宕機為客觀下線,然後就會執行故障的切換等過程
三、Redis群集模式
3.1、什麼是Cluster群集模式
Redis Cluster是Redis提供的分散式資料庫方案,叢集通過分片(sharding)來進行資料共享,並提供複製和故障轉移功能,從Redis3.0版本開始正式提供。
Redis 的哨兵模式基本已經可以實現高可用,讀寫分離 ,但是在這種模式下每臺 Redis 伺服器都儲存相同的資料,很浪費記憶體,所以在 redis3.0上加入了 Cluster 叢集模式,實現了 Redis 的分散式存儲,也就是說每臺 Redis 節點上儲存不同的內容。
3.2、群集的作用
(1)資料分割槽:資料分割槽(或稱資料分片)是叢集最核心的功能。 叢集將資料分散到多個節點,一方面突破了Redis單機記憶體大小的限制,儲存容量大大增加;另一方面每個主節點都可以對外提供讀服務
和寫服務,大大提高了叢集的響應能力。 Redis單機記憶體大小受限問題,在介紹持久化和主從複製時都有提及;例如,如果單機記憶體太大,bgsave和bgrewriteaof的fork操作可能導致主程序阻塞,主從環
境下主機切換時可能導致從節點長時間無法提供服務,全量複製階段主節點的複製緩衝區可能溢位。
(2)高可用:叢集支援主從複製和主節點的自動故障轉移(與哨兵類似);當任一節點發生故障時,叢集仍然可以對外提供服務。
3.3、群集的資料分片
Redis 叢集沒有使用一致性 hash,而是引入了雜湊槽【hash slot】的概念。
Redis 叢集有16384 個雜湊槽,每個 key 通過 CRC16 校驗後對 16384 取模來決定放置哪個槽。叢集的每個節點負責一部分hash槽,舉個例子,比如當前叢集有3個節點,那麼:
- 節點 A 包含 0 到 5460 號雜湊槽
- 節點 B 包含 5461 到 10922 號雜湊槽
- 節點 C 包含 10923 到 16383 號雜湊槽
這種結構很容易新增或者刪除節點。比如如果我想新添加個節點 D , 我需要將節點 A, B, C 中的部分槽移動到 節點D 上。如果我想移除節點 A ,需要將 A 中的槽移到 B 和 C 節點上,然後將沒有任何槽的 A 節點從叢集中移除即可。由於從一個節點將雜湊槽移動到另一個節點並不會停止服務,所以無論新增刪除或者改變某個節點的雜湊槽的數量都不會造成叢集不可用的狀態。在 Redis 的每一個節點上,都有這麼兩個東西,一個是插槽(slot),它的的取值範圍是:0-16383。還有一個就是 cluster,可以理解為是一個叢集管理的外掛。當我們的存取的 Key到達的時候,Redis會根據 CRC16 的演算法得出一個結果,然後把結果對 16384 求餘數,這樣每個 key 都會對應一個編號在 0-16383 之間的雜湊槽,通過這個值,去找到對應的插槽所對應的節點,然後直接自動跳轉到這個對應的節點上進行存取操作。
四、實驗搭建 主從複製,哨兵模式,群集模式
4.1、搭建redis主從複製
環境配置
master 192.168.118.100 slave1 192.168.118.101 slave2 192.168.118.102
所有伺服器搭建redis資料庫
所有節點都要安裝redis這邊只展示一臺的搭建過程
1 關閉防火牆 2 systemctl stop firewalld 3 setenforce 0 4 #安裝依賴環境 5 yum install -y gcc gcc-c++ make 6 7 #解壓檔案到指定資料夾 opt 8 tar zxvf redis-5.0.7.tar.gz -C /opt/ 9 cd /opt/redis-5.0.7/ 10 #安裝 11 make 12 make PREFIX=/usr/local/redis install 13 #執行軟體包提供的install_server.sh 指令碼檔案,設定Redis服務所需要的相關配置檔案 14 cd /opt/redis-5.0.7/utils 15 ./install_server.sh 16 …… 17 慢慢回車 18 Please select the redis executable path [] 19 手動輸入 20 /usr/local/redis/bin/redis-server 21 22 #建立軟連結 23 ln -s /usr/local/redis/bin/* /usr/local/bin/ 24 25 /etc/init.d/redis_6379 stop #停止 26 /etc/init.d/redis_6379 start #啟動 27 /etc/init.d/redis_6379 restart #重啟 28 /etc/init.d/redis_6379 status 29 30 #重啟redis服務 31 /etc/init.d/redis_6379 restart
修改Redis配置檔案(Master節點操作)
1 vim /etc/redis/6379.conf 2 bind 0.0.0.0 #70行,修改監聽地址為0.0.0.0 3 daemontze yes #137行,開啟守護程序 4 logfile/var/log/redis_6379.1og #172行,指定日誌檔案目錄 5 dir/var/lib/redis/6379 #264行,指定工作目錄 6 appendonly yes #700行,開啟AOF持久化功能 7 /etc/init.d/redis_6379 restart
修改Redis配置檔案(slave節點操作)
1 vim /etc/redis/6379.conf 2 3 bind 0.0.0.0 #70行,修改監聽地址為0.0.0.0 4 daemonize yes #137行,開啟守護程序 5 logfile/var/log/redis 6379.1og #172行,指定日誌檔案目錄 6 dir/var/lib/redis/6379 #264行,指定工作目錄 7 replicaof 192.168.52.140 6379#288行,指定要同步的Master節點IP和埠 8 appendonly yes #700行,開啟AOF持久化功能 9 /etc/init.d/redis_6379 restart 10 netstat -natp | grep redis
slave節點配置與master節點類似使用scp命令進行遠端傳輸後進行修改
scp /etc/redis/6379.conf 192.168.118.101:/etc/redis scp /etc/redis/6379.conf 192.168.118.102:/etc/redis
進入兩臺slave伺服器進行修改
1 vim /etc/redis/6379.conf 2 replicaof 192.168.52.140 6379#288行,指定要同步的Master節點IP和埠 3 /etc/init.d/redis_6379 restart 4 netstat -natp | grep redis 檢視主從伺服器是否連線
驗證主從效果
在Master節點上看日誌
在Master節點上驗證從節點
在master節點上新增資料 從節點檢視
4.2、搭建redis哨兵模式
環境配置
master 192.168.118.100 slave1 192.168.118.101 slave2 192.168.118.102 sentinel-1: 192.168.118.103 sentinel-2: 192.168.118.104 sentinel-3: 192.168.118.105
所有哨兵伺服器安裝好redis服務
搭建主從複製的時候給過詳細步驟這邊就不配圖了
1 關閉防火牆 2 systemctl stop firewalld 3 setenforce 0 4 #安裝依賴環境 5 yum install -y gcc gcc-c++ make 6 7 #解壓檔案到指定資料夾 opt 8 tar zxvf redis-5.0.7.tar.gz -C /opt/ 9 cd /opt/redis-5.0.7/ 10 #安裝 11 make 12 make PREFIX=/usr/local/redis install 13 #執行軟體包提供的install_server.sh 指令碼檔案,設定Redis服務所需要的相關配置檔案 14 cd /opt/redis-5.0.7/utils 15 ./install_server.sh 16 …… 17 慢慢回車 18 Please select the redis executable path [] 19 手動輸入 20 /usr/local/redis/bin/redis-server 21 22 #建立軟連結 23 ln -s /usr/local/redis/bin/* /usr/local/bin/ 24 25 /etc/init.d/redis_6379 stop #停止 26 /etc/init.d/redis_6379 start #啟動 27 /etc/init.d/redis_6379 restart #重啟 28 /etc/init.d/redis_6379 status 29 30 #重啟redis服務 31 /etc/init.d/redis_6379 restart
master和slave部署Redis主從複製
####這邊我之前做好主從複製了,這邊就不重複做了,省略這一步
修改哨兵節點的配置檔案sentinel.conf(所有哨兵節點操作)
- 此處修改192.168.118.103哨兵節點的配置檔案,使用scp命令傳給其他兩個哨兵節點
vim /opt/redis-5.0.7/sentinel.conf protected-mode no #17行,關閉保護模式 port 26379 #21行,Redis哨兵預設的監聽埠 daemonize yes #26行,指定sentine1為後臺啟動 logfile "/var/log/sentinel.log" #36行,指定日誌存放路徑 dir "/var/lib/redis/6379" #65行,指定資料庫存放路徑 sentinel monitor mymaster 192.168.118.100 6379 2 #84行,修改指定該哨兵節點監控192.168.118.100:6379這個主節點,該主節點的名稱是mymaster,最後的2的含義與主節點的故障判定有關:至少需要2個哨兵節點同意,才能判定主節點故障並進行故障轉移 sentinel down-after-milliseconds mymaster 3000 #113行,判定伺服器down掉的時間週期,預設30000毫秒(30秒) sentinel failover-timeout mymaster 180000 #146行,同一個sentine1對同一個master兩次failover之間的間隔時間(180秒) #遠端傳續將配置檔案傳輸給其他哨兵伺服器 scp /opt/redis-5.0.7/sentinel.conf 192.168.118.104:/opt/redis-5.0.7/ scp /opt/redis-5.0.7/sentinel.conf 192.168.118.105:/opt/redis-5.0.7/
啟動哨兵模式
#所有哨兵伺服器執行 cd /opt/redis-5.0.7/ redis-sentinel sentinel.conf &
在哨兵節點檢視哨兵訊息
故障模擬
#在master節點檢視redis-server程序號 ps -ef | grep redis #殺死master節點redis-server程序 kill -9 79754
在哨兵節點上驗證master是否轉換至從伺服器
redis-cli -p 26379 info sentinel
故障恢復
1 #主節點 2 rm -rf /var/run/redis_6379.pid #刪除pid檔案如果pid檔案不刪除則服務起不來 3 /etc/init.d/redis_6379 start #啟動服務 4 netstat -natp |grep 6379 5 #主伺服器檢視 6 redis-cli info replication
4.3、搭建redis群集模式
實驗環境配置
- redis的叢集一般需要6個節點,3主3從,每個節點都要安裝redis
伺服器型別 | 系統和IP地址 | 需要安裝的元件 |
master1 | 192.168.118.100 | redis-5.0.7.tar.gz |
master2 | 192.168.118.101 | redis-5.0.7.tar.gz |
master3 | 192.168.118.102 | redis-5.0.7.tar.gz |
slave1 | 192.168.118.103 | redis-5.0.7.tar.gz |
slave2 | 192.168.118.104 | redis-5.0.7.tar.gz |
slave3 | 192.168.118.105 | redis-5.0.7.tar.gz |
修改任意一臺伺服器配置檔案
vim /opt/redis-5.0.7/redis.conf bind 192.168.118.100 #69行,註釋掉bind項,改為自己 protected-mode no #88行,修改,關閉保護模式 port 6379 #92行redis預設監聽埠, daemonize yes #136行,開啟守護程序,以獨立程序啟動 appendonly yes #700行,修改,開啟AOF持久化 cluster-enabled yes #832行,取消註釋,開啟群集功能 cluster-config-file nodes-6001.conf #840行,取消註釋,群集名稱檔案設定 cluster-node-timeout 15000 #846行,取消註釋群集超時時間設定 #遠端傳輸完要修改監聽地址為自己 scp /opt/redis-5.0.7/redis.conf 192.168.118.101:/opt/redis-5.0.7/ scp /opt/redis-5.0.7/redis.conf 192.168.118.102:/opt/redis-5.0.7/ scp /opt/redis-5.0.7/redis.conf 192.168.118.103:/opt/redis-5.0.7/ scp /opt/redis-5.0.7/redis.conf 192.168.118.104:/opt/redis-5.0.7/ scp /opt/redis-5.0.7/redis.conf 192.168.118.105:/opt/redis-5.0.7/
啟動redis節點所有節點執行
cd /opt/redis-5.0.7/ redis-server redis.conf #啟動redis節點
啟動叢集
叢集開啟成功
遇到的報錯及解決辦法
當我開啟叢集時,開啟失敗並報出以下錯誤提示
[ERR] Node 192.168.118.100:6379 is not configured as a cluster node.
先說下我當時的排錯思路
- 檢查埠是否開啟成功
- 檢視配置檔案redis.conf群集設定是否開啟
檢查埠時發現監聽地址是0.0.0.0,感覺有點不對勁,還有/usr/local/redis/bin/redis-server地址也不是我剛建立的,我才想起來,我在部署redis服務的時候使用指令碼安裝,腳本里是使用預設的服務目錄啟動
找到問題了,我們將之前開的服務關閉,在開啟叢集。
/etc/init.d/redis_6379 stop ###關閉服務 redis-server redis.conf ###重新開啟 ps -ef | grep redis ###檢視是否開啟 root 7628 1 0 08:46 ? 00:00:00 redis-server 192.168.118.100:6379 [cluster] ###這時監聽地址已經恢復正確 root 7633 7252 0 08:46 pts/2 00:00:00 grep --color=auto redis
接下來重新開啟叢集就可以正常開啟了。