redis的Cluster集羣學習

Share猿,一個極客共同交流學習的社區!

關鍵詞

  • cluster
  • 去中心化
  • 節點槽位
  • 網絡抖動
  • CRC16算法(槽位定位算法)

記錄

關於cluster

RedisCluster 是redis的親兒子,他是redis做者本身提供的redis集羣解決方案。node

問題

1.cluster是去中心化的集羣,什麼是去中心化集羣?

去中心化集羣指的就是各個節點之間都是平等的,並且每一個節點具備高度自治的特徵,節點之間相互鏈接通信保持數據的一致性。咱們最熟知的去中心應用比特幣系統,就是一個去中心化的系統。redis

2.cluster爲何要將全部數據劃分爲 16384 的 slots(槽位)?

2.1什麼是solts(槽位,又稱爲hash槽)?

經過上一節學習codies集羣,咱們知道codies有1024個槽位,爲何cluster集羣會有這麼多,什麼是槽位/hash槽哪?算法

槽位其實就至關於咱們緩存桶,16384個槽位就至關於16384個存儲數據的緩存桶,cluster集羣會把這個16384個緩存桶均勻分配給集羣的各個節點數組

節點A覆蓋0-5460;緩存

節點B覆蓋5461-10922;安全

節點C覆蓋10923-16383.ruby

當咱們在集羣中放置一個key-value的時候,cluster會根據CRC16(key)mod16384得出的值,該值決定咱們的key-value放到哪一個緩存桶裏面。bash

當咱們新增集羣節點的時候,新增的集羣節點會從現有的各個節點中獲取一部分緩存桶網絡

節點A覆蓋1365-5460app

節點B覆蓋6827-10922

節點C覆蓋12288-16383

節點D覆蓋0-1364,5461-6826,10923-12287

看到這裏,想必你們也知道什麼是redis cluster的槽位,爲何cluster集羣的槽位比codies多的緣由。

2.2.基於上面的回答我又提出一個問題,去中心化節點是把槽位均分到各個集羣節點上,假如咱們其中一個節點掛了,整個集羣豈不是掛了??

通過網上查資料,發現,所謂的去中心化節點準確的說應該是去中心化主節點,上面的ABC節點在部署的時候咱們還要對其部署對應的從節點,這樣才能保證其中一個主節點掛了而不影響整個集羣。因此cluster集羣是一種:去中心化+主從的集羣模式

2.3.關於槽位定位算法

Cluster 默認會對 key 值使用 crc16 算法進行 hash 獲得一個整數值,而後用這個整數值對 16384 進行取模來獲得具體槽位

Cluster 還容許用戶強制某個 key 掛在特定槽位上,經過在 key 字符串裏面嵌入 tag 標記,這就能夠強制 key 所掛在的槽位等於 tag 所在的槽位

3.什麼是cluster跳轉?

3.1.什麼是cluster的轉?

說的直白一點就是從一個節點跳到另外一個集羣節點。

3.2.如何跳轉?

當咱們對一個集羣節點發送了一個指令,發現該節點不存在該指令的槽位,這時它會向客戶端發送一個特殊的跳轉指令攜帶目標操做的節點地址,告訴客戶端去連這個節點去獲取數據。

GET x
-MOVED 3999 127.0.0.1:6381複製代碼

MOVED 指令的第一個參數 3999 是 key 對應的槽位編號,後面是目標節點地址。MOVED 指令前面有一個減號,表示該指令是一個錯誤消息。

客戶端收到 MOVED 指令後,要當即糾正本地的槽位映射表。後續全部 key 將使用新的槽位映射表。

4.cluster集羣如何進行多個節點之間數據的遷移?

Redis Cluster 提供了工具 redis-trib 可讓運維人員手動調整槽位的分配狀況,它使用 Ruby 語言進行開發,經過組合各類原生的 Redis Cluster 指令來實現。

redis-trib提供了UI界面方便咱們的遷移,還提供了自動平衡槽位的工具,無需人工干預就能均衡集羣負載。

4.1.遷移過程

從源節點獲取內容 => 存到目標節點 => 從源節點刪除內容。

5.redis的cluster集羣是如何保證容錯性的?

Redis Cluster 能夠爲每一個主節點設置若干個從節點,單主節點故障時,集羣會自動將其中某個從節點提高爲主節點。若是某個主節點沒有從節點,那麼當它發生故障時,集羣將徹底處於不可用狀態。不過 Redis 也提供了一個參數cluster-require-full-coverage能夠容許部分節點故障,其它節點還能夠繼續提供對外訪問。

6.什麼是網絡抖動?cluster集羣如何防止網絡抖動帶來的數據不一致性?

所謂網絡抖動就是網絡異常狀況,忽然不可訪問,一下子又好了。這種狀況可能致使cluster的主從節點頻繁切換。

針對上述狀況,cluster提供了一個選項cluster-node-timeout,他存在的意義在於防止網絡抖動而引發頻繁的節點切換。設置了該選項只有當節點長期失聯的時候纔會進行主從切換。

7.cluster是如何判斷一個節點是否下線的?

只有當大多數節點都認定了某個節點失聯了,集羣才認爲該節點須要進行主從切換來容錯。

一個節點發現某個節點失聯了 (PFail),它會將這條信息向整個集羣廣播,其它節點也就能夠收到這點失聯信息。

若是一個節點收到了某個節點失聯的數量 (PFail Count) 已經達到了集羣的大多數,就能夠標記該節點爲肯定下線狀態 (Fail),而後向整個集羣廣播,強迫其它節點也接收該節點已經下線的事實,並當即對該失聯節點進行主從切換。

8.如何使用cluster集羣?(redis-py 客戶端不支持 Cluster 模式)

要使用 Cluster,必須安裝另一個包,這個包是依賴 redis-py 包的。pip install redis-py-cluster

>>> from rediscluster import StrictRedisCluster
>>> # Requires at least one node for cluster discovery. Multiple nodes is recommended.
>>> startup_nodes = [{"host": "127.0.0.1", "port": "7000"}]
>>> rc = StrictRedisCluster(startup_nodes=startup_nodes, decode_responses=True)
>>> rc.set("foo", "bar")
True
>>> print(rc.get("foo"))
'bar'複製代碼

Cluster 是去中心化的,它有多個節點組成,構造 StrictRedisCluster 實例時,咱們能夠只用一個節點地址,其它地址能夠自動經過這個節點來發現。不過若是提供多個節點地址,安全性會更好。若是隻提供一個節點地址,那麼當這個節點掛了,客戶端就必須更換地址才能夠繼續訪問 Cluster。 第二個參數 decode_responses 表示是否要將返回結果中的 byte 數組轉換成 unicode。

Cluster 使用起來很是方便,用起來和普通的 redis-py 差異不大,僅僅是構造方式不一樣。可是它們也有至關大的不同之處,好比 Cluster 不支持事務,Cluster 的 mget 方法相比 Redis 要慢不少,被拆分紅了多個 get指令,Cluster 的 rename 方法再也不是原子的,它須要將數據從原節點轉移到目標節點。

9.cluster集羣是如何感知槽位遷移的?

客戶端保存了槽位和節點的映射關係表,它須要即時獲得更新,才能夠正常地將某條指令發到正確的節點中。

10.cluster集羣發生變動客戶端是如何接受到通知的?

咱們前面提到 Cluster 有兩個特殊的 error 指令,一個是 moved,一個是 asking。

第一個 moved 是用來糾正槽位的。

第二個 asking 指令和 moved 不同,它是用來臨時糾正槽位的。

moved 和 asking 指令都是重試指令,客戶端會由於這兩個指令多重試一次。

11.嘗試本身搭建一個cluster集羣

11.1. 準備配置文件

建立cluster目錄,並建立6個配置文件

11.2. 修改配置文件

port 7000 //端口7000,7002,7003..
daemonize yes //redis後臺運行
pidfile ./redis_7000.pid //pidfile文件對應7000,7001,7002
cluster-enabled yes //開啓集羣 把註釋#去掉
cluster-config-file nodes_7000.conf //集羣的配置 配置文件首次啓動自動生成 7000,7001,7002
cluster-node-timeout 15000 //請求超時 默認15秒,可自行設置
appendonly yes //aof日誌開啓 有須要就開啓,它會每次寫操做都記錄一條日誌
//若設置密碼,master和slave需同時配置下面兩個參數:
masterauth "12345678" //鏈接master的密碼
requirepass "12345678" //本身的密碼

11.3. 啓動、測試全部redis實例

  • 建立啓動文件:vi start-all.sh
  • 賦予權限:chmod u+x start-all.sh
  • 啓動:./start-all.sh

11.4. 安裝redis-trib所需的 ruby腳本

ruby redis-trib.rb //測試是否安裝成功,若已經安裝過,可跳過此步

安裝

cp /usr/andy/redis/redis-3.2.0/src/redis-trib.rb .

yum install ruby

yum install rubygems

gem install redis-3.2.2.gem //需下載redis-3.2.2.gem

11.5. 使用redis-trib.rb建立集羣

執行下面命令建立集羣(需爲真實ip,否則外網沒法訪問):

./redis-trib.rb create --replicas 1 192.168.0.217:7000 192.168.0.217:7001 192.168.0.217:7002 192.168.0.217:7003 192.168.0.217:7004 192.168.0.217:7005

能夠看到:

  • 7003是7000主節點的從節點,管理槽0-5460
  • 7004是7001主節點的從節點,管理槽5461-10992
  • 7005是7002主節點的從節點,管理槽10992-16383

12.使用客戶端操做對cluster集羣進行一些常規指令的操做

集羣

cluster info :打印集羣的信息

cluster nodes :列出集羣當前已知的全部節點( node),以及這些節點的相關信息。

節點

cluster meet ip port:將 ip 和 port 所指定的節點添加到集羣當中,讓它成爲集羣的一份子。

cluster forget <node_id> :從集羣中移除 node_id 指定的節點。

cluster replicate <node_id> :將當前節點設置爲 node_id 指定的節點的從節點。

cluster saveconfig :將節點的配置文件保存到硬盤裏面。

槽(slot)

cluster addslots <slot> [slot ...] :將一個或多個槽( slot)指派( assign)給當前節點。

cluster delslots <slot> [slot ...] :移除一個或多個槽對當前節點的指派。

cluster flushslots :移除指派給當前節點的全部槽,讓當前節點變成一個沒有指派任何槽的節點。

cluster setslot <slot> node <node_id> :將槽 slot 指派給 node_id 指定的節點,若是槽已經指派給另外一個節點,那麼先讓另外一個節點刪除該槽>,而後再進行指派。

cluster setslot <slot> migrating <node_id> :將本節點的槽 slot 遷移到 node_id 指定的節點中。

cluster setslot <slot> importing <node_id> :從 node_id 指定的節點中導入槽 slot 到本節點。

cluster setslot <slot> stable :取消對槽 slot 的導入( import)或者遷移( migrate)。

cluster keyslot <key> :計算鍵 key 應該被放置在哪一個槽上。

cluster countkeysinslot <slot> :返回槽 slot 目前包含的鍵值對數量。

cluster getkeysinslot <slot> <count> :返回 count 個 slot 槽中的鍵

覆盤

學完這一小節明白了cluster集羣的基本原理,以及槽位等一些相關概念,瞭解了CRC16算法,學會如何搭建一個cluster集羣。

掃描如下二維碼關注社區公衆號↓↓↓↓↓↓↓↓

更多資訊請在簡書、微博、今日頭條、掘金、CSDN均可以經過搜索「Share猿」加入Share猿社區!!!

相關文章
相關標籤/搜索