Redis系列五:redis主從複製(replication)、哨兵(sentinel)、集羣(cluster)

1、Redis主從複製

主從複製:主節點負責寫數據,從節點負責讀數據,主節點按期把數據同步到從節點保證數據的一致性node

1. 主從複製的相關操做

  1. 配置主從複製方式1、新增redis6380.conf, 加入 slaveof 192.168.152.128 6379, 在6379啓動完後再啓6380,完成配置;
  2. 配置主從複製方式2、redis-server --slaveof 192.168.152.128 6379 臨時生效
  3. 查看狀態:info replication
  4. 斷開主從複製:在slave節點,執行6380:>slaveof no one
  5. 斷開後再變成主從複製:6380:> slaveof 192.168.152.128 6379
  6. 數據較重要的節點,主從複製時使用密碼驗證: requirepass
  7. 從節點建議用只讀模式slave-read-only=yes, 若從節點修改數據,主從數據不一致 

傳輸延遲:主從通常部署在不一樣機器上,複製時存在網絡延時問題,redis提供repl-disable-tcp-nodelay參數決定是否關閉TCP_NODELAY,默認爲關閉
參數關閉時:不管大小都會及時發佈到從節點,佔帶寬,適用於主從網絡好的場景,
參數啓用時:主節點合併全部數據成TCP包節省帶寬,默認爲40毫秒發一次,取決於內核,主從的同步延遲40毫秒,適用於網絡環境複雜或帶寬緊張,如跨機房redis

2. Redis主從拓撲

a)一主一從:用於主節點故障轉移從節點,當主節點的「寫」命令併發高且須要持久化,能夠只在從節點開啓AOF(主節點不須要),這樣即保證了數據的安全性,也避免持久化對主節點的影響 算法

 

b)一主多從:針對「讀」較多的場景,「讀」由多個從節點來分擔,但節點越多,主節點同步到多節點的次數也越多,影響帶寬,也加劇主節點的穩定數據庫

 

c)樹狀主從:一主多從的缺點(主節點推送次數多壓力大)可用些方案解決,主節點只推送一次數據到從節點B,再由從節點B推送到C,減輕主節點推送的壓力。安全

3. 主從複製原理

 

4. 數據同步

redis 2.8版本以上使用psync命令完成同步,過程分「全量」與「部分」複製
全量複製:通常用於初次複製場景(第一次創建SLAVE後全量)
部分複製:網絡出現問題,從節點再次鏈接主節點時,主節點補發缺乏的數據,每次數據增量同步
心跳:主從有長鏈接心跳,主節點默認每10S向從節點發ping命令,repl-ping-slave-period控制發送頻率網絡

5. 主從的缺點

a)主從複製,若主節點出現問題,則不能提供服務,須要人工修改配置將從變主
b)主從複製主節點的寫能力單機,能力有限
c)單機節點的存儲能力也有限併發

6.主從故障如何故障轉移

a)主節點(master)故障,從節點slave-1端執行 slaveof no one後變成新主節點;
b)其它的節點成爲新主節點的從節點,並重新節點複製數據;
c)須要人工干預,沒法實現高可用。tcp

2、Redis哨兵機制(Sentinel)

1. 爲何要有哨兵機制?

       哨兵機制的出現是爲了解決主從複製的缺點的分佈式

2. 哨兵機制(sentinel)的高可用

  原理:當主節點出現故障時,由Redis Sentinel自動完成故障發現和轉移,並通知應用方,實現高可用性。函數

其實整個過程只須要一個哨兵節點來完成,首先使用Raft算法(選舉算法)實現選舉機制,選出一個哨兵節點來完成轉移和通知

3. 哨兵的定時監控任務

任務1:每一個哨兵節點每10秒會向主節點和從節點發送info命令獲取最拓撲結構圖,哨兵配置時只要配置對主節點的監控便可,經過向主節點發送info,獲取從節點的信息,並當有新的從節點加入時能夠立刻感知到

任務2:每一個哨兵節點每隔2秒會向redis數據節點的指定頻道上發送該哨兵節點對於主節點的判斷以及當前哨兵節點的信息,同時每一個哨兵節點也會訂閱該頻道,來了解其它哨兵節點的信息及對主節點的判斷,其實就是經過消息publish和subscribe來完成的

 任務3:每隔1秒每一個哨兵會向主節點、從節點及其他哨兵節點發送一次ping命令作一次心跳檢測,這個也是哨兵用來判斷節點是否正常的重要依據

客觀下線:當主觀下線的節點是主節點時,此時該哨兵3節點會經過指令sentinel is-masterdown-by-addr尋求其它哨兵節點對主節點的判斷,當超過quorum(選舉)個數,此時哨兵節點則認爲該主節點確實有問題,這樣就客觀下線了,大部分哨兵節點都贊成下線操做,也就說是客觀下線

 

4. 領導者哨兵選舉流程

a)每一個在線的哨兵節點均可以成爲領導者,當它確認(好比哨兵3)主節點下線時,會向其它哨兵發is-master-down-by-addr命令,徵求判斷並要求將本身設置爲領導者,由領導者處理故障轉移;
b)當其它哨兵收到此命令時,能夠贊成或者拒絕它成爲領導者;
c)若是哨兵3發現本身在選舉的票數大於等於num(sentinels)/2+1時,將成爲領導者,若是沒有超過,繼續選舉…………

 

5. 故障轉移機制

a)由Sentinel節點按期監控發現主節點是否出現了故障

sentinel會向master發送心跳PING來確認master是否存活,若是master在「必定時間範圍」內不迴應PONG 或者是回覆了一個錯誤消息,那麼這個sentinel會主觀地(單方面地)認爲這個master已經不可用了

 

 

 b) 當主節點出現故障,此時3個Sentinel節點共同選舉了Sentinel3節點爲領導,負載處理主節點的故障轉移

 

 c) 由Sentinel3領導者節點執行故障轉移,過程和主從複製同樣,可是自動執行

 

 流程:

    1. 將slave-1脫離原從節點,升級主節點,

         2. 將從節點slave-2指向新的主節點

         3. 通知客戶端主節點已更換

         4. 將原主節點(oldMaster)變成從節點,指向新的主節點

 d) 故障轉移後的redis sentinel的拓撲結構圖

6. 哨兵機制-故障轉移詳細流程-確認主節點

a) 過濾掉不健康的(下線或斷線),沒有回覆過哨兵ping響應的從節點

b) 選擇salve-priority從節點優先級最高(redis.conf)的

c) 選擇複製偏移量最大,指複製最完整的從節點

7. 實戰:如何安裝和部署哨兵

以3個Sentinel節點、2個從節點、1個主節點爲例進行安裝部署

1. 前提:先搭好一主兩從redis的主從複製,和以前的主從複製搭建同樣,搭建方式以下:

  A)主節點6379節點(/usr/local/bin/conf/redis6379.conf):

    修改 requirepass 12345678,註釋掉#bind 127.0.0.1

  B) 從節點redis6380.conf和redis6381.conf: 配置都同樣

 

    修改 requirepass 12345678 ,註釋掉#bind 127.0.0.1, 

    加上訪問主節點的密碼masterauth 12345678 ,加上slaveof 192.168.152.128 6379

    注意當主從起來後,主節點可讀寫,從節點只可讀不可寫

2. redis sentinel哨兵機制核心配置(也是3個節點):

       /usr/local/bin/conf/sentinel_26379.conf  

       /usr/local/bin/conf/sentinel_26380.conf

       /usr/local/bin/conf/sentinel_26381.conf

將三個文件的端口改爲: 26379   26380   26381

而後:sentinel monitor mymaster 192.168.152.128 6379 2  //監聽主節點6379

      sentinel auth-pass mymaster 12345678     //鏈接主節點時的密碼

三個配置除端口外,其它同樣。

3. 哨兵其它的配置:只要修改每一個sentinel.conf的這段配置便可:

sentinel monitor mymaster 192.168.152.128 6379 2  

//監控主節點的IP地址端口,sentinel監控的master的名字叫作mymaster,2表明,當集羣中有2個sentinel認爲master死了時,才能真正認爲該master已經不可用了

sentinel auth-pass mymaster 12345678  //sentinel連主節點的密碼

sentinel config-epoch mymaster 2  //故障轉移時最多能夠有2從節點同時對新主節點進行數據同步

sentinel leader-epoch mymaster 2

sentinel failover-timeout mymasterA 180000 //故障轉移超時時間180s,                            

a,若是轉移超時失敗,下次轉移時時間爲以前的2倍;

b,從節點變主節點時,從節點執行slaveof no one命令一直失敗的話,當時間超過180S時,則故障轉移失敗

c,從節點複製新主節點時間超過180S轉移失敗

sentinel down-after-milliseconds mymasterA 300000//sentinel節點按期向主節點ping命令,當超過了300S時間後沒有回覆,可能就認定爲此主節點出現故障了……

sentinel parallel-syncs mymasterA 1 //故障轉移後,1表明每一個從節點按順序排隊一個一個複製主節點數據,若是爲3,指3個從節點同時併發複製主節點數據,不會影響阻塞,但存在網絡和IO開銷

4. 啓動redis服務和sentinel服務:

a)先把以前安裝的redis裏面的標綠色的文件都拷貝到 usr/local/bin目錄下,而後再再bin目錄下新建一個conf文件夾存放配置好的redis主從配置文件和哨兵配置文件

b)啓動主從複製服務,先啓動主再啓動從

主:./redis-server conf/redis6379.conf &

從:

  ./redis-server conf/redis6380.conf &

  ./redis-server conf/redis6381.conf &      

 

c)啓動sentinel服務:

       ./redis-sentinel conf/sentinel_26379.conf &

       ./redis-sentinel conf/sentinel_26380.conf &

     

 ./redis-sentinel conf/sentinel_26381.conf &

到此服務所有啓動完畢

 

鏈接到6379的redis的服務,可看到6379就是主節點,他有6380和6381兩個從節點

5. 測試:kill -9 6379  殺掉6379的redis服務

能夠看到殺掉6379之後6380變爲了主節點,6381變爲了6380的從節點

從新啓動6379之後變爲6380的從節點

看日誌是分配6380 是6381的主節點,當6379服務再啓動時,已變成從節點

假設6380升級爲主節點:進入6380>info replication     能夠看到role:master

打開sentinel_26379.conf等三個配置,sentinel monitor mymaster 192.168.152.128 6380 2

打開redis6379.conf等三個配置, slaveof 192.168.152.128 6380,也變成了6380

注意:生產環境建議讓redis Sentinel部署到不一樣的物理機上。

8.部署建議

a,sentinel節點應部署在多臺物理機(線上環境)

b,至少三個且奇數個sentinel節點

c,經過以上咱們知道,3個sentinel可同時監控一個主節點或多個主節點

    監聽N個主節點較多時,若是sentinel出現異常,會對多個主節點有影響,同時還會形成sentinel節點產生過多的網絡鏈接,

    通常線上建議仍是, 3個sentinel監聽一個主節點

3、redis集羣

Redis集羣的概念:

  RedisCluster是redis的分佈式解決方案,在3.0版本後推出的方案,有效地解決了Redis分佈式的需求,當一個服務掛了能夠快速的切換到另一個服務,當遇到單機內存、併發等瓶頸時,可以使用此方案來解決這些問題。

一、分佈式數據庫

 1)分佈式數據庫把整個數據按分區規則映射到多個節點,即把數據劃分到多個節點上,每一個節點負責總體數據的一個子集。好比咱們庫有900

2)分區規則

常見的分區規則哈希分區和順序分區,redis集羣使用了哈希分區,順序分區暫用不到,不作具體說明;

   rediscluster採用了哈希分區的「虛擬槽分區」方式(哈希分區分節點取餘、一致性哈希分區和虛擬槽分區),其它兩種也不作介紹,有興趣能夠百度瞭解一下

3) 虛擬槽分區(槽:slot)

   RedisCluster採用此分區,全部的鍵根據哈希函數(CRC16[key]&16383)映射到0-16383槽內,共16384個槽位,每一個節點維護部分槽及槽所映射的鍵值數據

   哈希函數: Hash()=CRC16[key]&16383 按位與

   槽與節點的關係以下

redis用虛擬槽分區緣由:解耦數據與節點關係,節點自身維護槽映射關係,分佈式存儲

4)redisCluster的缺陷

a,鍵的批量操做支持有限,好比mset, mget,若是多個鍵映射在不一樣的槽,就不支持了 

b,鍵事務支持有限,當多個key分佈在不一樣節點時沒法使用事務,同一節點是支持事務

c,鍵是數據分區的最小粒度,不能將一個很大的鍵值對映射到不一樣的節點

d,不支持多數據庫,只有0,select 0

e,複製結構只支持單層結構,不支持樹型結構。

 

二、集羣節點之間的通訊

 1) 節點之間採用Gossip協議進行通訊,Gossip協議就是指節點彼此之間不斷通訊交換信息

 

當主從角色變化或新增節點,彼此經過ping/pong進行通訊知道所有節點的最新狀態並達到集羣同步

 2)Gossip協議

Gossip協議的主要職責就是信息交換,信息交換的載體就是節點之間彼此發送的Gossip消息,經常使用的Gossip消息有ping消息、pong消息、meet消息、fail消息

 

meet消息:用於通知新節點加入,消息發送者通知接收者加入到當前集羣,meet消息通訊完後,接收節點會加入到集羣中,並進行週期性ping pong交換

ping消息:集羣內交換最頻繁的消息,集羣內每一個節點每秒向其它節點發ping消息,用於檢測節點是在在線和狀態信息,ping消息發送封裝自身節點和其餘節點的狀態數據;

pong消息,當接收到ping meet消息時,做爲響應消息返回給發送方,用來確認正常通訊,pong消息也封閉了自身狀態數據;

fail消息:當節點斷定集羣內的另外一節點下線時,會向集羣內廣播一個fail消息,

3) 消息解析流程

全部消息格式爲:消息頭、消息體,消息頭包含發送節點自身狀態數據(好比節點ID、槽映射、節點角色、是否下線等),接收節點根據消息頭能夠獲取到發送節點的相關數據。

消息解析流程:

 

 

 

4) 選擇節點併發送ping消息:

  Gossip協議信息的交換機制具備自然的分佈式特性,但ping pong發送的頻率很高,能夠實時獲得其它節點的狀態數據,但頻率高會加劇帶寬和計算能力,所以每次都會有目的性地選擇一些節點; 可是節點選擇過少又會影響故障判斷的速度,redis集羣的Gossip協議兼顧了這二者的優缺點,看下圖:

 

不難看出:節點選擇的流程能夠看出消息交換成本主要體如今發送消息的節點數量和每一個消息攜帶的數據量

流程說明:

A,選擇發送消息的節點數量:集羣內每一個節點維護定時任務默認爲每秒執行10次,每秒會隨機選取5個節點,找出最久沒有通訊的節點發送ping消息,用來保證信息交換的隨機性,每100毫秒都會掃描本地節點列表,若是發現節點最近一次接受pong消息的時間大於cluster-node-timeout/2 則馬上發送ping消息,這樣作目的是防止該節點信息太長時間沒更新,當咱們寬帶資源緊張時,在可redis.conf將cluster-node-timeout 15000  改爲30秒,但不能過分加大

B,消息數據:節點自身信息和其餘節點信息

三、redis集羣擴容

這也是分佈式存儲最多見的需求,當咱們存儲不夠用時,要考慮擴容

擴容步驟以下:

A. 準備好新節點

B. 加入集羣,遷移槽和數據

1) 同目錄下新增redis6382.conf、redis6392.conf兩個redis節點

啓動兩個新redis節點

./redis-server clusterconf/redis6382.conf &  (新主節點)

./redis-server clusterconf/redis6392.conf &   (新從節點)

2) 新增主節點

 ./redis-trib.rb add-node 192.168.152.128:6382 192.168.152.128:6379  

6379是原存在的主節點,6382是新的主節點

 

3),添加從節點

redis-trib.rb add-node --slave --master-id 03ccad2ba5dd1e062464bc7590400441fafb63f2 192.168.152.128:6392 192.168.152.128:6379  

    --slave,表示添加的是從節點

    --master-id 03ccad2ba5dd1e062464bc7590400441fafb63f2表示主節點6382的master_id

    192.168.152.128:6392,新從節點

    192.168.152.128:6379集羣原存在的舊節點

 

4) redis-trib.rb reshard 192.168.152.128:6382   //爲新主節點從新分配solt

How many slots do you want to move (from 1 to 16384)? 1000 //設置slot數1000

What is the receiving node ID? 464bc7590400441fafb63f2 //新節點node id

Source node #1:all //表示所有節點從新洗牌

新增完畢!

四、集羣縮減節點

集羣同時也支持節點下線掉,下線的流程以下:

流程說明:

A,肯定下線節點是否存在槽slot,若是有,須要先把槽遷移到其餘節點,保證整個集羣槽節點映射的完整性;

B,當下線的節點沒有槽或自己是從節點時,就能夠通知集羣內其它節點(或者叫忘記節點),當下線節點被忘記後正常關閉。

刪除節點也分兩種:

一種是主節點6382,一種是從節點6392。

在從節點6392中,沒有分配哈希槽,執行

./redis-trib.rb del-node 192.168.1.111:6392 7668541151b4c37d2d9 有兩個參數ip:port  和節點的id。 從節點6392從集羣中刪除了。

主節點6382刪除步驟:

1)./redis-trib.rb reshard 192.168.1.111:6382

  問咱們有多少個哈希槽要移走,由於咱們這個節點上剛分配了1000 個因此咱們這裏輸入1000

2)最後

./redis-trib.rb del-node 192.168.1.111:6382 3e50c6398c75e0088a41f908071c2c2eda1dc900

此時節點下線完成……

五、故障轉移

redis集羣實現了高可用,當集羣內少許節點出現故障時,經過故障轉移能夠保證集羣正常對外提供服務。

當集羣裏某個節點出現了問題,redis集羣內的節點經過ping pong消息發現節點是否健康,是否有故障,其實主要環節也包括了 主觀下線和客觀下線;

主觀下線:指某個節點認爲另外一個節點不可用,即下線狀態,固然這個狀態不是最終的故障斷定,只能表明這個節點自身的意見,也有可能存在誤判;

 

 

下線流程:

A,節點a發送ping消息給節點b ,若是通訊正常將接收到pong消息,節點a更新最近一次與節點b的通訊時間;

B,若是節點a與節點b通訊出現問題則斷開鏈接,下次會進行重連,若是一直通訊失敗,則它們的最後通訊時間將沒法更新;

節點a內的定時任務檢測到與節點b最後通訊時間超過cluster_note-timeout時,更新本地對節點b的狀態爲主觀下線(pfail)

客觀下線:指真正的下線,集羣內多個節點都認爲該節點不可用,達成共識,將它下線,若是下線的節點爲主節點,還要對它進行故障轉移

假如節點a標記節點b爲主觀下線,一段時間後節點a經過消息把節點b的狀態發到其它節點,當節點c接受到消息並解析出消息體時,會發現節點b的pfail狀態時,會觸發客觀下線流程;

當下線爲主節點時,此時redis集羣爲統計持有槽的主節點投票數是否達到一半,當下線報告統計數大於一半時,被標記爲客觀下線狀態。

故障恢復:

故障主節點下線後,若是下線節點的是主節點,則須要在它的從節點中選一個替換它,保證集羣的高可用;轉移過程以下:

 

1,資格檢查:檢查該從節點是否有資格替換故障主節點,若是此從節點與主節點斷開過通訊,那麼當前從節點不具體故障轉移;

2,準備選舉時間:當從節點符合故障轉移資格後,更新觸發故障選舉時間,只有到達該時間後才能執行後續流程;

3,發起選舉:當到達故障選舉時間時,進行選舉;

4,選舉投票:只有持有槽的主節點纔有票,會處理故障選舉消息,投票過程實際上是一個領導者選舉(選舉從節點爲領導者)的過程,每一個主節點只能投一張票給從節點,當從節點收集到足夠的選票(大於N/2+1)後,觸發替換主節點操做,撤銷原故障主節點的槽,委派給本身,並廣播本身的委派消息,通知集羣內全部節點。

相關文章
相關標籤/搜索