Redis進階一之淺析redis各種部署方案

一、單機模式

單機模式架構圖如下:

單機模式比較好理解,就是整個系統中只有一個redis節點,需要爲所有連接的客戶端提高讀寫服務,在小型項目中通過採用單機模式就可以正常工作。但是在中大型的項目架構中,單節點就會有一些問題會暴露出來。

1、內存瓶頸,數據量大時一臺節點的內存無法存儲所有的數據

2、IO瓶頸,客戶端數量較多時,同時處理的客戶端數量有限,且是單線程處理,無法同時處理太多的客戶端請求

3、可用性不高,一旦單節點宕機,就會導致整個redis不可用

單機模式的使用和原理不復雜,無需過多贅述。

二、主從模式

主從模式是在單機模式的基礎之上,增加了N個從節點,主節點主要負責客戶端的寫操作,從節點則負責客戶端的讀操作,另外從節點需要實時同步從節點的寫操作,以保證主從節點的數據一致性。

優點:讀寫分離,讀的壓力分散到從節點,主節點宕機從節點仍然可以提供讀服務

缺點:

1、主節點依然承受所有的寫壓力;

2、每個節點的數據都一模一樣,可存儲數據的總量和單機一樣,依然沒有解決單節點的數據容量問題;

3、主機宕機,宕機前的未同步到slave節點的數據會丟失

4、主機宕機,需要手動配置新的master節點

 

2.1、主從模式的實現

小編測試機器有限,是在虛擬機上通過yum安裝了redis服務,首先通過systemctl redis start 啓動master節點的服務,接下來就是啓動從節點服務的步驟

1、首先複製配置redis.conf文件,重命名爲redis-slave1.conf

2、修改redis-slave1.conf中的內容,主要修改內容如下:

# 配置監聽的端口號(和master節點區分開)
port 7000

# 副本配置, 如果當前節點屬於從節點,通過配置masterip和masterport配置主節點的ip和端口
slaveof localhost 6379

# 如果主節點配置了密碼校驗,那麼通過配置masterauth配置主節點的密碼
masterauth  master節點密碼(如果有的話)

# 從節點是否只讀,默認配置yes表示從節點只讀;如果配置no表示從節點可寫,但是不建議從節點可寫
slave-read-only yes

 

核心配置實際就兩個,一個是修改端口號避免和master節點衝突(不同節點無所謂),然後就是添加master節點的配置,slaveof master節點IP  master節點端口號

3、啓動redis服務,找到redis-server啓動腳本,按指定配置文件執行

/usr/bin/redis-server   /etc/redis-slave1.conf & 

4、啓動成功之後,可以通過redis可視化管理工具查看,可以看到從節點會自動將主節點上的所有數據同步過去,並且後續主節點數據更新,會同步到從節點

另外從節點配置了slave-read-only yes之後表示從節點只可讀不可寫,如果向從節點寫執行寫操作,會直接拋異常:READONLY You can't write against a read only slave.

2.2、主從模式的工作原理

1、主節點啓動,提供正常的讀寫服務

2、從節點啓動,和主節點建立TCP連接

3、從節點向主節點發生psync命令表示需要同步數據

4、主節點接收到psync之後執行bgsave命令生成RDB內存快照文件

5、主節點的RDB文件生成完成之後通過TCP連接發送給從節點,並且將之後的寫命令存入緩存區

6、從節點接收到RDB文件之後開始寫入本地內存中

7、主節點將緩衝區的寫命令發生給從節點,從節點執行寫命令(此時主從節點數據保持了一致)

8、主節點在執行寫命令時會將寫命令同步給從節點

三、哨兵模式

3.1、哨兵模式簡介

Sentinel(哨兵)用於監控redis集羣中節點的運行狀態,通過監控master和slave節點的狀態,並通過故障轉移的方式保證了redis集羣的高可用性。Sentinel系統通常會包含多個sentinal實例,因爲單個哨兵可能會由於本身的原因而出現誤判的情況。所以通常一個哨兵系統至少應該需要有三個sentinal實例。哨兵主要有以下三個作用:

1、監控:通過不停的向master和slave節點以及其他Sentinal發送ping,來監控其他節點運行狀態

2、提醒:當監控的Redis節點出現異常,會通過API向其他程序發生通知

3、故障轉移:當Sentinal系統檢測某個master不可用時,Sentinal系統會進行一次故障轉移操作,將故障的master節點的其中一個slave節點升級爲新的master,並通知其他的slave節點更新master節點信息爲新的master。原因的master節點會變成slave節點。

當客戶端訪問已經故障的master節點時,集羣會返回新的master節點給客戶端使用。

3.2.、哨兵模式原理

1、每個哨兵會每秒向監控的master、slave以及其他Sentinel節點發生ping命令,確保監控的節點正常運行

2、如果一個實例回覆距離最後一次有效回覆ping命令的時間超過down-after-milliseconds配置的值,就會被Sentinal標記爲主觀下線

3、如果一個master被標記主觀下線,則正在監視這個master的所有Sentinal都以每秒ping一次來確認master已經主觀下線

4、當足夠數量的Sentinal(超過一半)都認爲master以及下線,那麼Master就會最終被標記爲客觀下線,也就是在集羣中以及被確認不可用了

5、每個Sentinal會以每10秒一次向所有的master、slave節點發生INFO命令

6、當Master被Sentinel標記客觀下線後,Sentinel向下線的Master對應的所有Slave發送INFO命令會從10秒一次改成1秒一次

7、如沒有足夠數量的Sentinel認爲master已經下線,Master的客觀下線狀態會被移除。且活Master重新下Sentinel的ping命令返回有效回覆,主觀下線狀態也會被移除

3.3、故障轉移的步驟

1、從客觀下線的master節點的所有slave節點中挑選一個新的Master節點

2、向所有slave節點發送新的Master節點的信息,所有Slave節點更新Master節點信息

3、下線的Master節點變成新Master節點的Slave節點,恢復正常時會變成Slave節點

四、集羣模式

 

集羣模式最大的區別就在於master節點不止一個,而是可以有N個,每個master節點再分配N個slave節點,這樣就相當於集羣模式是有N個主從模式構成的。每個master節點存儲的數據不一樣,這樣就間接的解決了單機master節點的存儲容量問題,和達不到高可用的問題。集羣模式下可以有多個master節點,存儲容量相當於翻倍,另外某一個master節點宕機不可用,其他master節點仍然繼續可以提供工作,使得整個集羣仍然處於高可用狀態。

4.1、集羣模式的使用

集羣模式通常爲了提供高可用性,至少需要3個master節點和3個slave節點

1、複製redis.conf文件,依次複製成3個master的配置和3個slave的配置

2、master的conf配置文件主要需要配置集羣信息,配置cluster-enabled則表示爲開啓了集羣模式

1 #開啓redis的集羣模式
2 cluster-enabled yes
3 
4 #配置集羣模式下的配置文件(依具體的端口號爲準)
5 cluster-config-file nodes-6379.conf
6 
7 #集羣內節點之間支持最長響應時間
8 cluster-node-timeout 15000

 

3、slave的conf配置主要配置各自的master節點信息即可,可參考主從模式配置方案

4、依次執行命令啓動各個redis服務,啓動3個master服務和3個slave服務

/usr/bin/redis-server  /etc/redis1.conf. &
/usr/bin/redis-server  /etc/redis2.conf. &
/usr/bin/redis-server  /etc/redis3.conf. &
/usr/bin/redis-server  /etc/redis-slave1.conf. &
/usr/bin/redis-server  /etc/redis-slave2.conf. &
/usr/bin/redis-server  /etc/redis-slave3.conf. &

 

5、執行結果如下,通過ps -ef | grep 'redis' 可以看出3個master節點組成了redis集羣

 

6、此時通過任意一個master節點訪問key,都會報錯,提示如下:

 

雖然現在已經啓動了3個master節點,但是這3個節點之間還沒有存在任何的聯繫,此時就需要用到redis官方提供的redis-trib.rb工具進行集羣環境的搭建,首先就需要安裝ruby運行環境

1、通過ruby --version檢測是否安裝了ruby工具,如果沒有則安裝ruby,命令如下:

yum install ruby

yum install runbygems

然後安裝redis集羣需要的插件

gem install redis

結果提示如下:

[root@centos-7 bin]# gem install redis Fetching: redis-4.2.2.gem (100%) ERROR: Error installing redis: redis requires Ruby version >= 2.3.0.

由於通過yum安裝的ruby爲2.0.0版本,而redis集羣至少需要ruby的版本爲2.3.0版本,所以需要安裝高版本的ruby,至少需要安裝到2.3.0版本

2、安裝成功之後繼續執行gem install redis命令

3、創建redis集羣

./redis-trib.rb create --replicas 1 10.211.55.3:6379 10.211.55.3:7001  10.211.55.3:7002

此時redis集羣已經創建成功

 

4.2、redis集羣的工作原理

4.2.1、hash槽的分配

redis集羣將存儲工具分隔成2的14次方個也就是16384個哈希槽(slot),集羣中的每個master節點會平均分配哈希槽。如3個master節點就會依次分配slot位置爲:0~5460、5461~10922、10922~16383。所以redis集羣中的master節點最多不能超過哈希槽的總個數16384個。redis集羣中存取key時,會先通過CRC16算法將key進行計算得到一個hash值,然後將hash值對16384進行取模運算,這樣key就會被分配給對應的hash槽對應的master節點上。

每個master節點啓動的時候都會被分配部分hash槽

新增節點時:將其他節點的部分hash槽分配給新節點

刪除節點時:將被刪除節點的hash槽分配給其他節點

每個hash槽相當於是一個數據分區

4.2.2、節點之間的通信

redis集羣中所有的master節點都會通過gossip協議進行通信,redis集羣並非是集中式管理,也就是沒有集中的地方存儲所有的redis集羣master信息,而是每個redis master節點包包含了整個集羣的信息。

集中式的好處是數據只有一份,可以保證數據的一致性,並且更新的時候只需要更新一份即可,但是元數據頻繁更新會導致中心壓力較大

gossip:元數據分散存儲,元數據更新時有一定的延時。但是元數據更新是分散更新,降低了更新的壓力

1、節點通信

redis集羣中每個節點都會開放一個給客戶端的端口,比如默認6379,那麼和其他節點之間通信的端口就會在給客戶端端口數字上+10000,比如給客戶端的端口爲7000,那麼和其他節點通信用的端口就是17000

每個節點之間每隔一段時間就會互相發送ping消息,各個節點接收到ping消息之後會回覆pong消息。通過ping+pong機制達到心跳的監控效果。

另外每個節點之間會不斷的交換各自的元數據信息,如:故障信息、節點的增加和移除、哈希槽信息等。

2、ping消息

每個節點互相發送ping信息,ping信息由於發送比較頻繁會增加網絡負擔,每個節點每秒會發送10次ping,每次會選擇最多5個最久沒有通信的其他節點。如果發現某個節點通信延時達到了cluster_node_timeout/2,那麼立即發送ping,避免數據不一致

ping消息會帶上本身節點的信息,並且會帶上最少3個,最多總節點數-2個其他節點的信息用於同步。

4.2.3、客戶端請求重定向

客戶端向redis集羣中發送命令並不是發送給所有master節點,而是任意挑選一個master節點發送命令,master節點先根據key通過CRC16算法計算key,再計算對應的哈希槽。如果屬於當前節點就直接執行,否則就將計算的哈希槽對應的節點地址告訴客戶端,

客戶端重定向到對應的節點上去執行命令。每個master節點都知道其他節點所負責的哈希槽信息

由於客戶端會重定向,所以會額外增加一次網絡通信的消耗,所以針對客戶端可以進行優化,通過客戶端自己就能先計算哈希槽,並且知道整個集羣中各個節點負責的哈希槽,那麼就可以直接發送命令到對應的節點上,這樣就不需要再走一次重定向了。

4.2.4、JedisCluster的工作原理

JedisCluster初始化的時候,由於每個master節點都保存了整個集羣的哈希槽信息和每個節點負責的哈希槽,所以JedisCluster初始化的時候會隨機選擇一個Master節點,獲取哈希槽信息和節點哈希槽映射關係,存在本地緩存。

同時JedisCluster會給每個Master節點都創建一個JedisPool連接池,每個JedisCluster執行操作,首先根據key計算對應的哈希槽,在本地找到對應的節點信息,然後直接發送到對應的節點執行命令即可。

但是由於JedisCluster本地緩存可能已經數據不準了,可能在JedisCluster初始化之後redis集羣信息已經發送了改變了,那麼先向本地找到的節點發送命令,如果節點返回了需要重定向,那麼先通過這個節點更新下本地的哈希槽緩存信息。

再重新計算一次找到對應的節點。如果重複操作超過了5次還是失敗,那麼就直接拋異常了。

4.2.5、集羣模式故障處理

由於主從模式一旦master節點故障,從節點只能提供讀服務或者手動將slave節點升級爲master節點,所以增加了哨兵模式,通過哨兵監控master節點的狀態,一旦master故障就選取slave節點選舉爲新的master節點。

而集羣模式下已經兼容了主從模式和哨兵模式了。集羣模式下高可用性和主備切換原理如下:

1、判斷master節點宕機

集羣中如果某個master判斷另一個master宕機,那麼就標記爲主觀下線,如果多個節點都認爲這個節點宕機,那麼就會判斷爲客觀下線,也就是在整個集羣中不可用了

每個節點通過判斷ping、pong的時間是否超過cluster-node-timeout判斷是否下線,如果判斷下線就會在ping消息中通知其他節點交換信息,超過一半的節點都認爲主觀下線了就會被判定爲客觀下線

2、從節點過濾

master宕機需要從這個master節點的所有slave節點中挑選新的master,會檢查每個slave與master斷開連接的時間,如果超過了cluster-node-timeout * cluster-slave-validity-factor時長,表示和master斷開時間過長,會存在數據落後的情況,那麼就沒有資格稱爲新的master。

3、從節點選舉

哨兵:對所有從節點進行排序,slave priority,offset,run id

每個從節點,都根據自己對master複製數據的offset,來設置一個選舉時間,offset越大(複製數據越多)的從節點,選舉時間越靠前,優先進行選舉

所有的master node開始slave選舉投票,給要進行選舉的slave進行投票,如果大部分master node(N/2 + 1)都投票給了某個從節點,那麼選舉通過,那個從節點可以切換成master。從節點執行主備切換,從節點切換爲主節點

基本上redis cluster和哨兵模式的流程一樣,相當於集羣模式就自行具備了哨兵模式的功能。

 

Tips:

集羣模式和哨兵模式的區別?

1、哨兵模式將監控的功能交給所有的哨兵;集羣模式下監控的功能是由所有的master節點監控

2、故障轉移時哨兵模式會選舉一個leader哨兵來進行故障遷移工作;集羣模式下會選舉一個新的master節點來負責故障遷移工作

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章