Redis集群明細文檔

Redis目前版本是沒有提供集群功能的,如果要實現多臺Redis同時提供服務只能通過客戶端自身去實現(Memchached也是客戶端實現分布式)。目前根據文檔已經看到Redis正在開發集群功能,其中一部分已經開發完成,但是具體什么時候可以用上,還不得而知。文檔來源:http://redis.io/topics/cluster-spec

一、介紹

  該文檔是開發之中的redis集群實現細節。該文檔分成兩個部分,第一部分為在redis非穩定版本代碼分支上已經實現的,另外一部分為還需要去實現的。在未來若集群實現設計變更這些都可能被修改,但是相對來說,未實現的部分相較于已經實現的部分被修改的可能性更大些。該文檔包括了實現客戶端需要的各種細節,但是客戶端作者需要注意這些細節都有可能被修改。

二、什么是Redis集群

  集群是獨立服務器關于分布式與容錯實現的一個子集。在集群之中沒有中心節點與代理節點,設計的主要目的之一就是線性可伸縮的擴展(即隨意增刪節點)。集群為了保證數據的一致性而犧牲容錯性,所以當網絡故障和節點發生故障時這個系統會盡力去保證數據的一致性和有效性。(這里我們認為節點故障是網絡故障的一種特殊情況)

     為了解決單點故障的問題,我們同時需要masters 和 slaves。 即使主節點(master)和從節點(slave)在功能上是一致的,甚至說他們部署在同一臺服務器上,從節點也僅用以替代故障的主節點(即備節點不會被使用除非主節點發生故障而用來代替主節點)。 實際上應該說 如果對從節點沒有read-after-write(寫并立即讀取數據 以免在數據同步過程中無法獲取數據)的需求,那么從節點僅接受只讀操作。

三、已經實現的子集

  集群實現了在非分布式版本上的所有單個命令。復雜多命令操作例如集合sets的交集并集還沒有實現。通常情況下理論上對于不在同一個節點上的操作不會被實現。

   將來可能增加一種叫"Computation Node"的新節點類型(計算節點),這種節點主要用來處理在集群中multi-key的只讀操作。但是對于multi-key的只讀操作不會以集群傳輸到Computation Node節點再進行計算的方式實現。

    (有點繞啊,看英文吧:In the future it is possible that using the MIGRATE COPY command users will be able to use Computation Nodes to perform multi-key read only operations in the cluster, but it is not likely that the Redis Cluster itself will be able to perform complex multi key operations implementing some kind of transparent way to move keys around.)

  集群中的節點不像獨立服務器那樣支持多個數據庫,將會只有數據庫0,并且不支持select命令。

四、集群協議中的客戶端與服務器角色

  在集群中的節點,負責存儲數據,了解集群的狀態以及包括把數據key映射到對應的節點。集群中的任何一個節點都能夠自動發現其他節點和檢測到故障的節點,并且在必要是時候執行備節點提升為主節點的操作。

  集群節點使用TCP bus(連接總線)和二進制協議進行互聯并對任務進行分派。即每一個節點都使用TCP bus連接到集群中的其他節點。各節點使用gossip 協議發送消息:

    1)傳播消息(propagate information)以發現新節點,

    2)發送ping packets給集群其他節點以檢測其他節點是否工作正常,

  3)發送集群消息需要特定的信號條件

   集群連接總線也可以是在各個節點間傳播PUB/SUB消息。

   當集群中的節點不能滿足客戶端的請求時,可能會使用errors -MOVED and -ASK命令來告知重定向到可用節點。理論上客戶端允許向集群中的任意節點發送請求并在必要時會得到重定向應答,即客戶端不必關心集群的狀態。然而客戶端可以緩存數據keys與節點的映射關系以改免去服務器端再進行重定向,這在一定程度上可以提高性能。

五、關鍵字分布式模型

  key空間被分割成16384 個slots(節點),實際上集群最大節點數為16384 個。然后建議的最大值為小幾百個節點。所有的主節點將處理4096個百分比的slot。當集群穩定時(即沒有正在轉移某個slot到另外一個節點),則某個slot必定只被某個節點處理,然后某個節點可以同時處理多個槽。

  effectively setting an upper limit for the cluster size of 16384 nodes (however the suggested max size of nodes is in the order of ~ 1000 nodes).

  映射鍵值到指定槽值的算法如下:

  HASH_SLOT = CRC16(key) mod 4096

  在該文檔的附注1之中有CRC16算法介紹。

  使用12滿分的CRC1616位輸出,在我們的測試之中CRC16能夠很好的將各種類型的key映射到4096的空間之中。

六、集群節點的屬性

  在集群中的每個節點都有其在集群中唯一的ID,其ID160比特隨機數的十六進制表示。節點首次啟動時即獲取ID,節點將獲取其ID并保存在其配置文件之中,并且將一直使用該ID,直到該配置文件被系統管理員刪除。

  節點的ID作為集群中的節點識別,一個節點可能修改IP或地址但是不必須修改節點名稱。集群也能夠檢測到節點IPPORT的變化然后通過連接總線發送變更的協議通知。

  每個節點都有一些相關的信息,被其他節點所知道:

  1)該節點的IP地址與端口

  2)一些標志位

  3)該節點服務的key-slot

  4)最后一次通過集群連接總線發送ping的時間

  5)最后一次收到pong的時間

  6)該節點的備份節點數

  7)如果其為備份節點,則其主節點的ID(若該節點為主節點則該值為0000000

  通過CLUSTER NODES命令可以獲取該集群中的所有節點信息,包括主節點與備份節點。

  如下為一個示例:

 $ redis-cli cluster nodes
  d1861060fe6a534d42d8a19aeb36600e18785e04 :0 myself - 0 1318428930 connected 0-1364
  3886e65cc906bfd9b1f7e7bde468726a052d1dae 127.0.0.1:6380 master - 1318428930 1318428931   connected 1365-2729
  d289c575dcbc4bdd2931585fd4339089e461a27d 127.0.0.1:6381 master - 1318428931 1318428931   connected 2730-4095

  上述顯示各項信息依次為:ID、IPPORT、 FLAGS、最近發送PING的時間,最近接受到PONG時間、連接狀態、slots

 

七、節點間的握手(已實現)

  節點總是接受來自集群總線的端口連接請求,并且在收到ping請求時總是回復,即使ping的源節點非可信的。然而若發送端的節點非所在集群,則其消息將被丟棄。

  一個節點接受另一個節點為集群的一部分有如下兩種情況:

  1)假如一個節點使用一個MEET消息介紹自己。MEET消息很像一個PING消息,但是其要求接受者將其接受為集群的一部分。節點只有在收到管理員執行的CLUSTER MEET ip port 命令之后才會發送MEET消息到其他節點

  2)當一個節點已經被信任時,另一個節點也可以注冊其為該集群的一部分,將擴展該消息到其他節點。假如:A知道BB知道C,最后B將傳播伙伴信息到AC,這時A將注冊C為該網絡的一部分,并且試圖連接到C。

  這意味著,只要我們加入節點到任意連通圖,他們最終將自動實現全連接。該項意味著集群可以自動發現新節點,但是信任關系需要有管理員設定。這種方式使得集群更加強大并且確保集群不會因為IPPORT變更而導致多個集群互相混淆。

  所有的節點將試圖連接已知的所有其他節點。

八、移動重定向

  一個redis客戶端可以自由地將請求發送給集群中的任意一個節點,包括哪些slave節點。節點將分析查詢請求,如果不能接受將通過哈希算法計算該關鍵字歸屬的節點,如果計算出的關鍵字屬于自己處理,則查詢直接被處理,其他情況將根據該節點的持有的其他節點信息,計算出關鍵字哈希然后返回客戶端表示MOVED錯誤。

  MOVED錯誤,看起來如下:

GET x
  -MOVED 3999 127.0.0.1:6381

  錯誤信息中包括了該key哈希出來的slot,以及服務于該slot的節點地址信息,客戶端需要重新請求到指定地址的節點。注意,假如客戶端得到該信息后很長一段時間沒有發起請求,假如集群在此時重組了各個節點服務的slot,則再次請求時有可能再次接收到MOVED錯誤。

  因此根據集群節點的視圖以ID為標示來說,我們試圖只是簡單的暴露哈希slot與節點IP,port之間的映射關系??蛻舳瞬槐仨毜菓撛囍彺?/span>slot3999是由 127.0.0.1 6381節點提供服務。

  這種方式當有一個新的命令需要處理時,就可以計算其slot然后請求到特定的節點能夠增加成功率。

  當集群服務穩定后,最終所有的客戶端都有一張slot與節點的映射表,客戶端直接請求到正確的節點而不需要重定向,有助于提高集群的效率。

  客戶端應該也能夠處理本文檔描述的ASK命令的重定向。

九、集群動態重構

  集群支持在運行時動態增加與刪除節點,事實上對于增加或刪除節點執行的是相同操作,即將處理keyslot從一個節點移動到另一個節點。

  1)增加一個新節點時,有一個空的節點添加到集群之中,同時會有一些哈希slot從現存的節點移動到新的節點上

  2)刪除一個節點,同樣的將其處理的哈希slot移動到其他節點之上

  因此實現的核心是能夠移動哈希slot,實際上,哈希slot對應的就是一組關鍵字key,因此集群在重新哈希時其實就是將一些key從一個節點移動到另一個節點。

  要理解該內容,可以通過CLUSTER子命令來手動移動節點的哈希slot,有如下命令:

  CLUSTER ADDSLOTS slot1 [slot2] ... [slotN]
  CLUSTER DELSLOTS slot1 [slot2] ... [slotN]
  CLUSTER SETSLOT slot NODE node
  CLUSTER SETSLOT slot MIGRATING node
  CLUSTER SETSLOT slot IMPORTING node

  前面兩個命令 ADDSLOTSDELSLOTS只是簡單的從某個節點上增加刪除其處理的slot,當哈希slot分配完成后他們將通過集群協議將信息廣播到所有節點。ADDSLOTS通常用于從零配置一個集群的快速方法。SETSLOTS用于將某個哈希slot分配給指定的已存在的節點。其他情況哈希slot可以通過另外兩種方法設置:MIGRATING、INPORTING

  1)當一個哈希slot被設置成MIGRATING,該節點會接受所有對該哈希slot的查詢,但是必須是該key已經存在。其他情況,將指引一個ASK重定向到MIGRATING的目標節點

  2)當一個哈希slot被設置成IMPORTTING,該節點會接受所有對該哈希slot的查詢,但是前提是必須執行一個ASKING命令。其他情況若客戶端沒有提供ASKING命令,則請求會被重定向到真實的服務該slot的節點上,產生一個MOVED錯誤。

  如此操作可能會奇怪,接下來會詳細說明。假定現在又兩個節點A、B,現在希望將slot 8從節點A移動到節點B,我們使用如下命令:  

We send B: CLUSTER SETSLOT 8 IMPORTING A
  We send A: CLUSTER SETSLOT 8 MIGRATING B

  此時,所有其他節點都會將查詢slot 8的請求定向到A,因此發生如下情況:

  1)所有已經存在的key查詢請求都在A中處理

  2)而所有未存在的key查詢請求都在B中處理

  這種方式我們不會在A中創建新的key,一個特殊的客戶端redis_trib作為集群的重配置將已經存在A中的key遷移到B之中,有如下命令執行:

  CLUSTER GETKEYSINSLOT slot count

  該命令返回某個slot中的key數量,對于每一個返回的key都會執行一個MIGRATE命令,該命令自動的將keyA遷移到B,這兩種情況下都將鎖定key因此沒有競爭條件。

 MIGRATE target_host target_port key target_database id timeout

  MIGRATE命令連接到目標實例,然后發送key的數據,當返回OK就從原有的數據庫中刪除該key,因此從外部客戶端看來同一時間key只存在于A或者B

  在redis集群中不需要指定而外的數據庫除了0,但是遷移MIGRATE命令可以用于非集群環境中,是一個通用的命令。遷移MIGRATE命令最優化執行遷移復雜的key例如lists。但是重新配置集群不是一個明智的操作特別是在應用程序有時間限制的時候。

十、ASK重定向

  在上一節我們簡單談及ASK重定向,為什么我們能夠簡單的使用MOVED重定向?因為MOVED意味著我們想要某個哈希slot永遠的由另一個節點提供服務,并且后續的查詢應該和試圖到特定的節點上。ASK只要求后續的查詢到特定的節點上。之所以需要如此是由于下次查詢slot 8的可能依然在A上,因此我們希望客戶端嘗試A之后如果需要再查詢B。由于只發生于4096分之一因此執行性能是可以接受的。

  然而我們需要確??蛻舳嗽谠噲D查詢A之后才查詢B,因此B對于設置為IMPORTINGslot的查詢只接受預先發送ASKING命令的查詢。簡單地ASKING命令用于設置一個標志位使得節點能夠為設置為IMPORTINGslot提供服務。

  因此對于ASK重定向,客戶端語義如下:

  1)若在發送查詢特定節點時收到ASK重定向信息

  2)使用ASKING請求作為命令的開始

  3)當前不需要修改本地的緩存將slot 8指向B

  當哈希slot 8遷移完成時,A將發送一個MOVED錯誤,此時客戶端可以將slot 8查詢緩存定向到B。即使客戶端過早的將slot 8緩存指向B,當想B查詢時沒有發送ASKING開頭,則B將會返回一個MOVED錯誤指向A。

十一、客戶端需要實現

 TODO Pipelining: use MULTI/EXEC for pipelining.
  TODO Persistent connections to nodes.
  TODO hash slot guessing algorithm.

容錯機制
十二、節點的錯誤檢測

  錯誤檢查使用如下機制:

  1)在一段時間內節點未響應發出的PING消息,則將其設置為PFAIL(可能錯誤)狀態。

  2)當ping其他節點時隨機帶上其他三個節點的信息,在信息的gossip節部分帶上其他節點的flag

  3)假如有一個節點設置為PFAIL,并且在收到的PING回復中其他節點也將其設置為PFAIL則將其設置為FAIL狀態

  4)當一個節點確認某個另外節點為FAIL時則發送消息到所有其他節點,強制收到該消息的節點將其設置為FAIL狀態

  因此一個節點在沒有獲取外面消息時無法獨立地將某個另外節點設置為FAIl

  仍然需要實現:當一個節點被標記為FAIL,當其他節點收到該節點的請求或連接時,將回復其“MARK AS FAIL”,當收到該消息時需要強制將自身設置為FAIL狀態。

十三、集群狀態檢查(部分實現)

  當集群發生變更時(更新slot或者一個節點被設置為fail等)每個節點都將檢查其保持的節點列表。

  一旦配置節點進入如下的階段:

  1)FAIL:集群不能工作,當一個節點進入該狀態,所有的請求將被拒絕并且返回一個錯誤。當節點檢查到集群不能同時為4096slot提供服務時進入該狀態

  2)OK:集群工作正常:所有的4096slot都能夠被節點服務到并且沒有FAIL節點

  這意味著集群在不能為所有的4096slot提供服務時停止工作。然而有一部分時間一個slot不能被訪問因為相關聯的節點有問題,但是該節點還未被設置為FAIL。在此時集群只能為其中的部分slot提供訪問服務。

  由于集群不支持MULTI、EXEC執行命令,因此程序員需要確保應用程序能夠從只有一部分查詢被集群接受的狀態中恢復。

十四、備節點選擇(未實現)

  每一個主節點都能夠有任意數量的從節點。從節點負責在主節點fail時設置自己為主節點。舉例:我們有節點A1A2,A3其中A1為主節點,A2,A3為從節點。假如A在某個階段FAIL并且沒有響應ping請求,最終其他節點通過gossip協議會將其設置為fail,當發生這種情況時,它的第一個從節點需要嘗試執行選擇。第一個從節點的概念非常簡單。所有的從節點根據node id進行排序,最小的就為第一個從節點,依次類推,當第一從節點也被標記為fail,在后續節點執行該選擇未主節點,以此類推。

  當一個配置變更時,錯有從節點檢查自身主節點是否為fail,若是則變更自身狀態為主節點并發送到所有的其他節點以變更配置。

十五、保護模式(未實現)

  當網絡不連通導致有孤立節點時,該節點會認為所有其他節點都為fail。這種時候他可能試圖選擇從節點或者更改集群配置。為了避免這種情況,節點認定其他主要節點為pfailfail要足夠長的時間以避免其采取其他動作。

  保護模式被清除之后,集群狀態就恢復正常了。

十六、主要的主節點規則

  作為網絡分離的結果之一,兩個或多個分割的部分可能為所有的哈希slot提供服務。由于集群努力保持一致性,這種情況不是我們想要的,而且網絡分割總是產生零個或單個可供操作的部分。如果他們有大部分原來的主節點,當這些規則節點被放到一個部分之中他們應該只提供查詢服務。

 十七、分發與訂閱(未實現需要重定義)

  在一個集群中的客戶端能夠訂閱任何一個節點,也能夠發布到任何一個節點。集群將確保若需要能夠得到轉發。當前實現只是簡單地廣播訂閱消息到所有節點,在某些時候這些將通過過濾或其他算法。

轉自:http://blog.csdn.net/hguisu/article/details/9165141

原創文章,作者:s19930811,如若轉載,請注明出處:http://www.www58058.com/2638

(0)
s19930811s19930811
上一篇 2015-04-04
下一篇 2015-04-04

相關推薦

  • Docker之~集群配置

    一、前言 Kubernetes 是Google開源的容器集群管理系統,基于Docker構建一個容器的調度服務,提供資源調度、均衡容災、服務注冊、動態擴縮容等功能套件,目前最新版本為0.6.2。 本文介紹如何基于Centos7.0構建Kubernetes平臺,在正式介紹之前,大家有必要先理解Kubernetes幾個核心概念及其承擔的功能。以下為Kubernet…

    2017-03-16
  • Linux軟件包管理工具yum詳解

    yum介紹 yum客戶端的使用 配置文件項作說明: 案例repo配置文件。 創建yum源命令(yum-config-manager) yum list相關命令 yum安裝 yum更新和升級 yum查找和顯示 yum刪除程序 查看倉庫 實戰演練本地yum倉庫(光盤) YUM內置變量 創建YUM倉庫(http) yum介紹 yum命令是在Fedora和RedHa…

    Linux干貨 2016-09-07
  • centos下nginx啟動腳本和chkconfig管理

    在安裝完nginx后,要用/usr/local/nginx/sbin/nginx來啟動nginx,顯然十分不方便。如果能像apache一樣,直接通過腳本進行管理就方便多了。 vim /etc/init.d/nginx 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27…

    Linux干貨 2017-09-27
  • N25期—第一周作業

    1、描述計算機的組成及其功能 計算機五大組成部件:運算器、控制器、存儲器、輸入設備和輸出設備。 運算器和控制器統稱中央處理器(CPU)。  存儲器分成內存儲器和外存儲器兩大類。  外存儲器、輸入設備和輸出設備統稱為外部設備。  中央處理器(CPU)  計算機的中央處理器又稱為CPU,它是計算機的核心部分。主要由運算器和…

    Linux干貨 2016-12-04
  • magedu_20160804

    文本處理工具和grep過濾工具以及正則表達式    一.文本處理工具相關命令    前面課程中曾經使用過cat,head,tail命令查看相關文件,head,tail分別查看文件開頭、結尾的行信息。對于特定想要顯示的信息則需要特定的文本查看指令,比如cut,sort,paste,uniq等。如下內容分別對每個…

    Linux干貨 2016-08-08
  • dns 服務

     DNS服務 1.正向解析    1. 創建解析庫                    2.改配置文件主要改 any no no 3個選項   3.添加一個解…

    2017-05-31
欧美性久久久久