redis集群演變(單機架構、主從架構、哨兵架構、redis-cluster架構)


redis集群演變(單節點、主從、哨兵、redis-cluster)

由於Redis是基於內存的高性能KV數據庫,這些年隨時Redis的快速發展,更多的技術開發者將Redis融入自己的實際項目中。為了應對各式各樣的業務場景保證數據更加穩定安全,各種高可用架構以及優化方案不斷改進,導致Redis的整個架構體系也有了一個演變過程。集群模式是近年來Redis架構不斷改進中較好的高可用方案。我們這里會對Redis的整個演變過程中每一個環節都進行一個介紹。主要包括了單機單節點模式、主從架構(M/S主從讀寫分離)、哨兵模式高可用架構、redis集群高可用架構等方案。

  • 單節點模式

最初Redis剛進入我們身邊的時候,是因為傳統關系型數據庫在某些特定場景下處理起來並不是十分合適,所以最初單機單節點的模式就能夠滿足我們對業務場景的應對,這里我們不做過多介紹這種模式,其實就是我們部署單個節點的Redis僅僅支持使用即可,對高可用以及數據安全性要求並不高。


總結一下:

優點

(1)優點也就是redis的優點,單機模式沒有什么好說的。

缺點

(1)redis就一個服務,掛了,整個緩存就癱瘓了。沒辦法高可用。

(2)數據持久化只存在當前這一個服務器,發生磁盤壞道時,備份數據就丟失了。這時redis掛了,恢復數據時就丟失數據了。

(3)讀寫操作都在一個redis服務上,服務壓力大。


搭建方式:

下載編譯運行,不多說。


  • 主從模式

隨着我們Redis不斷融入我們項目中各式各樣業務場景,我們發現其實在大多數時候甚至超過90%的情況下,我們只Redis進行讀操作,寫操作只是為了支撐緩存數據內容,一次寫操作之后伴隨的是大量的讀操作。所以Master-Slave主從架構出現了。

我們通過部署額外的一些Redis服務讓其與主服務器連接,主服務器會通過網絡發送數據副本給從服務器進行准實時更新。我們在應用的過程中將寫操作都集中在主服務器,而讀操作集中在從服務器,這樣就分散了主服務器的壓力,使其性能更好並且更具備可用性,並且同時部署多台從服務器也能很大程度上解決讀操作集中造成的性能瓶頸。

主從架構還有一個好處,那就是可以保證我們數據的安全性。我們知道Redis通過持久化的功能保證了服務器重啟之后只會損失少量數據甚至不會損失數據的問題。由於持久化會將我們內存中的數據保存到磁盤上,重啟之后會從磁盤上加載數據。但是由於數據僅會存儲在一台服務器上,當這台服務器磁盤故障那么數據也會出現丟失。為了避免這種單點故障造成的數據丟失,所以通常會部署多個服務到不同服務器上,也就能夠保證數據有多個備份,數據更加安全不易丟失。


總結一下:

優點

(1)讀寫分離了。大量的讀操作的壓力可以分擔到slave上。

(2)主從redis均保存着全量的數據,都做了持久化后,如果有一台機器磁盤出現壞道,也可以用其他機器的持久化文件來恢復。

缺點

(1)主服務器掛了,必須人工介入恢復,手動設置新的主服務器。不滿足高可用。


搭建方式:

假如搭建1主2從,一共3台redis服務器。

1主(6371)
2主(6372,6373)

6371的redis.conf:

port 6371  # 指定redis端口
requirepass password  # 按個人需要設置redis密碼

6372的redis.conf:

port 6372  # 指定redis端口
requirepass password  # 設置redis密碼
masterauth password  # 配置驗證主服務器的密碼,這里必須與6371的密碼配置一樣
slaveof [6371服務器的ip] 6371  # 指定主服務器的ip與端口

6373的redis.conf:

port 6373  # 指定redis端口
requirepass password  # 設置redis密碼
masterauth password  # 配置驗證主服務器的密碼,這里必須與6371的密碼配置一樣
slaveof [6373服務器的ip] 6371  # 指定主服務器的ip與端口

注:這里給出的只是最基本的配置,另外一些持久化的配置啊,淘汰策略的配置啊,日志文件的配置啊,需要自己去摸索。


  • 哨兵模式

在我們使用主從模式時,從節點主要有兩個作用:

(1)分擔主節點讀壓力,保證數據安全性。

(2)主節點宕機后,從節點可以作為主節點的備份頂上來。

那么如果主節點宕機后,我們需要如何操作?首先將即將頂替主節點的從節點取消主備,然后將另外的從節點綁定上新的主節點。

這整個過程,包括從節點晉升為主節點,其他從節點修改關聯主節點都需要人工操作,對於系統高可用都是不理想的方式。

但是,Redis已經給我們提供了Sentinel哨兵模式,哨兵模式就是自動幫我們去做災備故障轉移的一個機制。它的功能包含以下三個:

(1)監控(Monitoring): Sentinel 會不斷地檢查主服務器和從服務器是否運作正常。

(2)提醒(Notification): 當被監控的某個Redis服務器出現問題時, Sentinel可以通過API向管理員或者其他應用程序發送通知。

(3)自動故障遷移(Automatic failover): 當一個主服務器不能正常工作時,Sentinel會開始一次自動故障遷移操作,它會將失效主服務器的其中一個從服務器升級為新的主服務器,並讓失效主服務器的其他從服務器改為變更為新的主從關系。當客戶端試圖連接失效的主服務器時, 集群也會向客戶端返回新主服務器的地址,使得集群可以使用新主服務器代替失效服務器。


總結一下:

優點

(1)包含着主從架構的全部優點。

(2)主服務器掛了,不再需要人工介入恢復。哨兵可以直接把從服務器切換為主服務器。

缺點

(1)哨兵模式包含着主從模式。但是主從模式只能有一台主服務器來進行寫操作。雖然redis的並發量,官方宣稱有10W左右。但是萬一有大於10W的寫操作並發時,只有一台主服務器可能承受不住。

(2)當公司大規模使用緩存時,如果緩存數據過大,例如到達幾個T,十幾個T時。因為主從模式是每台機器都全量保存數據的,這樣每台機器的內存可能要到達幾個T,十幾個T。在做redis數據恢復時,耗時太長。


搭建方式:

假如搭建1主2從,3台哨兵,一共6台redis服務器。

1主(6371)
2主(6372,6373)
3哨兵(26371,26372,26373)

6371,6372,6373的配置跟主從模式的一樣。
26371,26372,26373的配置只有端口號不一樣。
下面只以26371作為示例:

26371的sentinel.conf:

port 26371  # 哨兵服務的端口
sentinel monitor mymaster [主服務器的ip] [主服務器的端口號] 2   # 配置監聽的主服務器,這里sentinel monitor代表監控,mymaster代表服務器的名稱,可以自定義,2代表只有兩個或兩個以上的哨兵認為主服務器不可用的時候,才會進行failover操作。
sentinel auth-pass mymaster password  # 配置哨兵的密碼

注:其他配置省略。在jedis中使用時,只需要配置好這三台哨兵的ip,端口,密碼就可以了。不需要配置主從服務器的節點信息。在建立連接時會訪問哨兵,哨兵會根據判斷是讀操作還是寫操作,自動返回主從節點信息,客戶端再去連接執行操作。


  • redis-cluster集群高可用架構

  • 集群原理分析

redis集群是一個由多個主從節點群組成的分布式服務器群,它具有復制、高可用和分片特性。Redis集群不需要sentinel哨兵也能完成節點移除和故障轉移的功能。需要將每個節點設置成集群模式,這種集群模式沒有中心節點,可水平擴展,據官方文檔稱可以線性擴展到上萬個節點(官方推薦不超過1000個節點)。redis集群的性能和高可用性均優於之前版本的哨兵模式,且集群配置非常簡單。

redis-cluster架構中,被設計成共有16384個hash slot。每個master分得一部分slot,其算法為:hash_slot = crc16(key) mod 16384 ,這就找到對應slot。采用hash slot的算法,實際上是解決了redis-cluster架構下,有多個master節點的時候,數據如何分布到這些節點上去。

  • 集群的糾正機制

當 Redis Cluster 的客戶端來連接集群時,它也會得到一份集群的槽位配置信息並將其緩存在客戶端本地。這樣當客戶端要查找某個 key 時,可以直接定位到目標節點。同時因為槽位的信息可能會存在客戶端與服務器不一致的情況,還需要糾正機制來實現槽位信息的校驗調整。

當客戶端向一個錯誤的節點發出了指令,該節點會發現指令的 key 所在的槽位並不歸自己管理,這時它會向客戶端發送一個特殊的跳轉指令攜帶目標操作的節點地址,告訴客戶端去連這個節點去獲取數據。客戶端收到指令后除了跳轉到正確的節點上去操作,還會同步更新糾正本地的槽位映射表緩存,后續所有 key 將使用新的槽位映射表。

  • 網絡抖動解決方案

真實世界的機房網絡往往並不是風平浪靜的,它們經常會發生各種各樣的小問題。比如網絡抖動就是非常常見的一種現象,突然之間部分連接變得不可訪問,然后很快又恢復正常。

為解決這種問題,Redis Cluster 提供了一種選項cluster-node-timeout,表示當某個節點持續 timeout 的時間失聯時,才可以認定該節點出現故障,需要進行主從切換。如果沒有這個選項,網絡抖動會導致主從頻繁切換 (數據的重新復制)。

  • 集群要求

集群至少需要3主3從。(關系到從服務的選舉。)


總結一下:

優點

(1)包含着上述架構的全部優點。

缺點

(1)部署優點麻煩算嗎?哈哈,如果用Docker應該會節省不少時間。


搭建方式:

redis集群需要至少要三個master節點,我們這里搭建三個master節點,並且給每個master再搭建一個slave節點,總共6個redis節點,這里用三台機器部署6個redis實例,每台機器一主一從,搭建集群的步驟如下:

第一步:
在第一台機器的/usr/local下創建文件夾redis-cluster,然后在其下面分別創建2個文件夾如下
(1)mkdir -p /usr/local/redis-cluster
(2)mkdir 8001、 mkdir 8004

第二步:
把之前的redis.conf配置文件copy到8001下,修改如下內容:

1. daemonize yes 
2. port 8001  # 分別對每個機器的端口號進行設置 
3. dir /usr/local/redis-cluster/8001/  # 指定數據文件存放位置,必須要指定不同的目錄位置,不然會丟失數據
4. cluster-enabled yes  # 啟動集群模式
5. cluster-config-file nodes-8001.conf  # 集群節點信息文件,這里800x最好和port對應上
6. cluster-node-timeout 5000
7. bind 0.0.0.0
8. appendonly yes
# 如果要設置密碼需要增加如下配置:
9. requirepass password     (設置redis訪問密碼)
10. masterauth password      (設置集群節點間訪問密碼,跟上面一致) 

第三步:
把修改后的配置文件,copy到8002,修改第2、3、5項里的端口號。

第四步:
另外兩台機器也需要做上面幾步操作,第二台機器用8002和8005,第三台機器用8003和8006。

第五步:
分別啟動6個redis實例,然后檢查是否啟動成功。
(1)/usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/800*/redis.conf
(2)ps -ef | grep redis 查看是否啟動成功

第六步:
用redis-cli創建整個redis集群(redis5以前的版本集群是依靠ruby腳本redis-trib.rb實現)

# 1代表為每個創建的主服務器節點創建一個從服務器節點  
/usr/local/redis-5.0.2/src/redis-cli -a password --cluster create --cluster-replicas 1 192.168.0.61:8001 192.168.0.62:8002 192.168.0.63:8003 192.168.0.61:8004 192.168.0.62:8005 192.168.0.63:8006 

第七步:
驗證集群:
(1)連接任意一個客戶端即可:./redis-cli -c -h -p (-a訪問服務端密碼,-c表示集群模式,指定ip地址和端口號)如:/usr/local/redis-5.0.2/src/redis-cli -a password -c -h 192.168.0.61 -p 800*
(2)進行驗證: cluster info(查看集群信息)、cluster nodes(查看節點列表)
(3)進行數據操作驗證
(4)關閉集群則需要逐個進行關閉,使用命令: /usr/local/redis/bin/redis-cli -a password -c -h 192.168.0.60 -p 800* shutdown

注:在jedis中使用時,需要配置集群全部節點的信息,只配置一台的話,雖然也是同樣的效果。但是如果這一台掛掉的話,整個集群就連接不上了。


集群擴容操作:

第一步:
啟動整個集群

/usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/8001/redis.conf
/usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/8002/redis.conf
/usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/8003/redis.conf
/usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/8004/redis.conf
/usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/8005/redis.conf
/usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/8006/redis.conf

第二步:
客戶端連接8001端口的redis實例

/usr/local/redis-5.0.2/src/redis-cli -a zhuge -c -h 192.168.0.61 -p 8001

第三步:
查看集群狀態

192.168.0.61:8001> cluster nodes

從上圖可以看出,整個集群運行正常,三個master節點和三個slave節點。
8001端口的實例節點存儲0-5460這些hash槽,
8002端口的實例節點存儲5461-10922這些hash槽,
8003端口的實例節點存儲10923-16383這些hash槽,
這三個master節點存儲的所有hash槽組成redis集群的存儲槽位,slave點是每個主節點的備份從節點,不顯示存儲槽位。

我們在原始集群基礎上再增加一主(8007)一從(8008),增加節點后的集群參見下圖,新增節點用虛線框表示:

第四步:
增加redis實例8007,8008。配置跟上面一樣。

第五步:
配置8007為集群主節點

/usr/local/redis-5.0.2/src/redis-cli --cluster add-node 192.168.0.64:8007 192.168.0.61:8001

查看集群狀態

注意:當添加節點成功以后,新增的節點不會有任何數據,因為它還沒有分配任何的slot(hash槽),我們需要為新節點手工分配hash槽。

第六步:
使用redis-cli命令為8007分配hash槽,找到集群中的任意一個主節點(紅色位置表示集群中的任意一個主節點),對其進行重新分片工作。

/usr/local/redis-5.0.2/src/redis-cli --cluster reshard 192.168.0.61:8001

輸出如下:
... ...
How many slots do you want to move (from 1 to 16384)? 600
(ps:需要多少個槽移動到新的節點上,自己設置,比如600個hash槽)

What is the receiving node ID? eb57a5700ee6f9ff099b3ce0d03b1a50ff247c3c
(ps:把這600個hash槽移動到哪個節點上去,需要指定節點id)
Please enter all the source node IDs.
Type "all" to use all the nodes as source nodes for the hash slots.
Type "done" once you entered all the source nodes IDs.
Source node 1:all
(ps:輸入all為從所有主節點(8001,8002,8003)中分別抽取相應的槽數指定到新節點中,抽取的總槽數為600個)
... ...

Do you want to proceed with the proposed reshard plan (yes/no)? yes
(ps:輸入yes確認開始執行分片任務)
... ...

第七步:
查看下最新的集群狀態:

如上圖所示,現在我們的8007已經有hash槽了,也就是說可以在8007上進行讀寫數據啦!到此為止我們的8007已經加入到集群中,並且是主節點(Master)。

第八步:
配置8008為8007的從節點

添加從節點8008到集群中去並查看集群狀態

/usr/local/redis-5.0.2/src/redis-cli --cluster add-node 192.168.0.64:8008 192.168.0.61:8001

如圖所示,還是一個master節點,沒有被分配任何的hash槽。

第九步:
我們需要執行replicate命令來指定當前節點(從節點)的主節點id為哪個,首先需要連接新加的8008節點的客戶端,然后使用集群命令進行操作,把當前的8008(slave)節點指定到一個主節點下(這里使用之前創建的8007主節點,紅色表示節點id)

/usr/local/redis-5.0.2/src/redis-cli -c -h 192.168.0.64 -p 8008

192.168.0.61:8008> cluster replicate eb57a5700ee6f9ff099b3ce0d03b1a50ff247c3c

第十步:
查看集群狀態,8008節點已成功添加為8007節點的從節點


集群縮容操作:

第一步:
 刪除8008從節點
用del-node刪除從節點8008,指定刪除節點ip和端口,以及節點id(紅色為8008節點id)

/usr/local/redis-5.0.2/src/redis-cli --cluster del-node 192.168.0.64:8008 1805b6339d91b0e051f46845eebacb9bc43baefe 

第二步:
再次查看集群狀態,如下圖所示,8008這個slave節點已經移除,並且該節點的redis服務也已被停止。

第三步:
最后,我們嘗試刪除之前加入的主節點8007,這個步驟相對比較麻煩一些,因為主節點的里面是有分配了hash槽的,所以我們這里必須先把8007里的hash槽放入到其他的可用主節點中去,然后再進行移除節點操作,不然會出現數據丟失問題(目前只能把master的數據遷移到一個節點上,暫時做不了平均分配功能),執行命令如下:

/usr/local/redis-5.0.2/src/redis-cli --cluster reshard 192.168.0.64:8007

輸出如下:
 ... ...

How many slots do you want to move (from 1 to 16384)? 600

What is the receiving node ID? deedad3c34e8437baa6ff013fd3d1461a0c2e761
(ps:這里是需要把數據移動到哪?8001的主節點id)

Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node 1:eb57a5700ee6f9ff099b3ce0d03b1a50ff247c3c
(ps:這里是需要數據源,也就是我們的8007節點id)
Source node 2:done
(ps:這里直接輸入done 開始生成遷移計划)
 ... ...

Do you want to proceed with the proposed reshard plan (yes/no)? Yes
(ps:這里輸入yes開始遷移)

至此,我們已經成功的把8007主節點的數據遷移到8001上去了,我們可以看一下現在的集群狀態如下圖,你會發現8007下面已經沒有任何hash槽了,證明遷移成功!

第四步:
最后我們直接使用del-node命令刪除8007主節點即可(紅色表示8007的節點id)。

/usr/local/redis-5.0.2/src/redis-cli --cluster del-node 192.168.0.64:8007    eb57a5700ee6f9ff099b3ce0d03b1a50ff247c3c

查看集群狀態,一切還原為最初始狀態啦!大功告成!



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM