Redis集羣

RedisCluster是redis的分佈式解決方案,在3.0版本後推出的方案,有效地解決了Redis分佈式的需求,當遇到單機內存、併發等瓶頸時,可以使用此方案來解決這些問題node

分佈式數據庫概念:

1,分佈式數據庫把整個數據按分區規則映射到多個節點,即把數據劃分到多個節點上,每一個節點負責總體數據的一個子集,好比咱們庫有900條用戶數據,有3個redis節點,將900條分紅3份,分別存入到3個redis節點redis

2,分區規則:數據庫

   常見的分區規則哈希分區和順序分區,redis集羣使用了哈希分區,順序分區暫用不到,不作具體說明;rediscluster採用了哈希分區的「虛擬槽分區」方式(哈希分區分節點取餘、一致性哈希分區和虛擬槽分區),其它兩種也不作介紹,有興趣能夠百度瞭解一下。ruby

3,虛擬槽分區(槽:slot)併發

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

   槽與節點的關係以下函數

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

4,redisCluster的缺陷:ui

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

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

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

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

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

集羣環境搭建-手動篇

 1,在/usr/local/bin/clusterconf目錄,

6389爲6379的從節點,6390爲6380的從節點,6391爲6381的從節點

2,分別修改637九、 6380、 738一、 638九、 6390、 6391配置文件

    port 6379                      //節點端口

   cluster-enabled yes              //開啓集羣模式

   cluster-node-timeout 15000       //節點超時時間(接收pong消息回覆的時間)

   cluster-config-file  /usrlocalbin/cluster/data/nodes-6379.conf 集羣內部配置文件

  其它節點的配置和這個一致,改端口便可

3,配置完後,啓動6個redis服務

命令:cd /usr/local/bin/clusterconf/data

          cat nodes-6379.conf  //查看6379節點ID值

        也能夠這樣查看        6379>cluster nodes

4,各節點啓動後,使用cluster meet ip port與各節點握手,是集羣通訊的第一步

5,握手成功後,使用cluster nodes能夠看到各節點均可以互相查詢到

6,節點握手成功後,此時集羣處理下線狀態,全部讀寫都被禁止

7,使用cluster info命令獲取集羣當前狀態

8,redis集羣有16384個哈希槽,要把全部數據映射到16384槽,須要批量設置槽

  redis-cli -h 127.0.0.1 -p 6379 cluster addslots {0...5461}

  但個人虛擬機按範圍分配有問題,同窗們回去試一下看有沒有問題

  錯誤爲: (error) ERR Invalid or out of range slot 

 

  批量不行,單個是能夠的

      redis-cli -h 127.0.0.1 -p 6379 cluster addslots 1 2 3 4

  所以,我寫一個腳本/usr/local/bin/addSlots.sh, 詳情可見些腳本……

  執行這個腳本可分配好槽位……

9,分配完槽後,可查看集羣狀態

10,而後再查看cluster nodes,查看每一個節點的ID

11,將6389,6390,6391與 6379,6380,6381作主從映射

    127.0.0.1:6389> cluster replicate af2c99b58aa8a0a8fd82ba594654ce9264ffb9bc

    127.0.0.1:6390> cluster replicate 2d6e6deb9512324336754b7b3fdf86032445c77c

   127.0.0.1:6391> cluster replicate 61bd9fbbd3c154da318b502b86b1ee6516b82c17

12,注:這是手動模式,在生產環境咱們通常採用如下自動模式安裝

 

自動安裝模式:

1,在/usr/local新建目錄:ruby

下載連接:https://pan.baidu.com/s/1kWsf3Rh 密碼:n3pc

從這個連接下載  ruby-2.3.1.tar.gz   和  redis-3.3.0.gem

解壓 tar -zxvf ruby-2.3.1.tar.gz

  a,  cd ruby-2.3.1

  b,  ./configure -prefix=/usr/local/ruby

  c,  make && make install   //過程會有點慢,大概5-10分鐘

  d, 而後gem install -l redis-3.3.0.gem  //沒有gem須要安裝yum install gem

  e,準備好6個節點,(注意不要設置requirepass),將/usr/local/bin/clusterconf/data的config-file刪除;依次啓動6個節點:./redis-server clusterconf/redis6379.conf

若是以前redis有數據存在,flushall清空;(坑:不須要cluster meet ..)

   f, 進入cd /usr/local/bin,  執行如下:1表明從節點的個數

./redis-trib.rb create --replicas 1 192.168.1.111:6379 192.168.1.111:6380 192.168.1.111:6381 192.168.1.111:6389 192.168.1.111:6390 192.168.1.111:6391

主從分配,6379是6389的從節點

貌似只有主節點可讀寫,從節點不能夠

主節點死後,從節點變成主節點

 

集羣健康檢測

redis-trib.rb check 192.168.1.111:6379   (注:redis先去註釋掉requirepass,否則連不上)

如此出現了這個問題,6379的5798槽位號被打開了

解決以下:

6379,6380,6381的有部分槽位被打開了,分別進入這幾個節點,執行

6380:>cluster setslot 1180 stable

            cluster setslot 2998 stable

            cluster setslot 11212 stable

其它也同樣,分別執行修復完後:

此時修復後的健康正常;

當停掉6379後,過會6389變成主節點

 

注意:使用客戶端工具查詢時要加-c

      ./redis-cli -h 192.168.1.111 -p 6379 -c

mset aa bb cc dd,批設置對應在不一樣的solt上,缺點

 

集羣正常啓動後,在每一個redis.conf里加上

   masterauth 「12345678」

   requiredpass 「12345678」

  當主節點下線時,從節點會變成主節點,用戶和密碼是頗有必要的,設置成一致

 

這上面是一主一從,那能不能一主多從呢?

./redis-trib.rb create --replicas 2

192.168.1.111:6379 192.168.1.111:6380 192.168.1.111:6381

192.168.1.111:6479 192.168.1.111:6480 192.168.1.111:6481

192.168.1.111:6579 192.168.1.111:6580 192.168.1.111:6581

 

節點之間的通訊

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

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

Gossip協議

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

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

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

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

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

 

消息解析流程

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

選擇節點併發送ping消息:

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

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

流程說明:

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

集羣擴容

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

擴容步驟以下:

1.準備好新節點

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

1),同目錄下新增redis6382.conf、redis6392.conf兩

啓動兩個新redis節點

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

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

 

2),新增主節點

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

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

 

3),添加從節點

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

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

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

    192.168.1.111:6392,新從節點

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

 

4),redis-trib.rb reshard 192.168.1.111: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 //表示所有節點從新洗牌

新增完畢!

 

集羣減縮節點:

    集羣同時也支持節點下線掉

    下線的流程以下:

流程說明:

  1. 肯定下線節點是否存在槽slot,若是有,須要先把槽遷移到其餘節點,保證整個集羣槽節點映射的完整性;
  2. 當下線的節點沒有槽或自己是從節點時,就能夠通知集羣內其它節點(或者叫忘記節點),當下線節點被忘記後正常關閉。

 刪除節點也分兩種:

    一種是主節點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接收的任何鍵相關命令首先是計算這個鍵CRC值,經過CRC找到對應的槽位,再根據槽找到所對應的redis節點,若是該節點是自己,則直接處理鍵命令;若是不是,則回覆鍵重定向到其它節點,這個過程叫作MOVED重定向

 

故障轉移:

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

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

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

下線流程:

  1. 節點a發送ping消息給節點b ,若是通訊正常將接收到pong消息,節點a更新最近一次與節點b的通訊時間;
  2. 若是節點a與節點b通訊出現問題則斷開鏈接,下次會進行重連,若是一直通訊失敗,則它們的最後通訊時間將沒法更新;
  3. 節點a內的定時任務檢測到與節點b最後通訊時間超過cluster_note-timeout時,更新本地對節點b的狀態爲主觀下線(pfail)

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

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

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

故障恢復:

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

  1. 資格檢查:檢查該從節點是否有資格替換故障主節點,若是此從節點與主節點斷開過通訊,那麼當前從節點不具體故障轉移;
  2. 準備選舉時間:當從節點符合故障轉移資格後,更新觸發故障選舉時間,只有到達該時間後才能執行後續流程;
  3. 發起選舉:當到達故障選舉時間時,進行選舉;
  4. 選舉投票:只有持有槽的主節點纔有票,會處理故障選舉消息,投票過程實際上是一個領導者選舉(選舉從節點爲領導者)的過程,每一個主節點只能投一張票給從節點,

當從節點收集到足夠的選票(大於N/2+1)後,觸發替換主節點操做,撤銷原故障主節點的槽,委派給本身,並廣播本身的委派消息,通知集羣內全部節點。

相關文章
相關標籤/搜索