Redis叢集知識解析

來源:互聯網
上載者:User

標籤:

 

 

redis叢集在啟動的時候就自動在多個節點間分好片。同時提供了分區之間的可用性:當一部分redis節點故障或網路中斷,叢集也能繼續工作。但是,當大面積的節點故障或網路中斷(比如大部分的主節點都不可用了),叢集就不能使用。

所以,從實用性的角度,Redis叢集提供以下功能:

  • 自動把資料切分到多個redis節點中
  • 當一部分節點掛了或不可達,叢集依然能繼續工作
Redis叢集的TCP連接埠

redis叢集中的每個節點都需要建立2個tcp串連,監聽這2個連接埠:一個連接埠稱之為“用戶端連接埠”,用於接受用戶端指令,與用戶端互動,比如6379;另一個連接埠稱之為“叢集匯流排連接埠”,是在用戶端連接埠號碼上加10000,比如16379,用於節點之間通過二進位協議通訊。各節點通過叢集匯流排檢測宕機節點、更新配置、容錯移轉驗證等。用戶端只能使用用戶端連接埠,不能使用叢集匯流排連接埠。請確保你的防火牆允許開啟這兩個連接埠,否則redis叢集沒法工作。用戶端連接埠和叢集匯流排連接埠之間的差值是固定的,叢集匯流排連接埠比用戶端連接埠高10000。

注意,關於叢集的2個連接埠:

  • 用戶端連接埠(一般是6379)需要對所有用戶端和叢集節點開放,因為叢集節點需要通過該連接埠轉移資料。
  • 叢集匯流排連接埠(一般是16379)只需對叢集中的所有節點開放

這2個連接埠必須開啟,否則叢集沒法正常工作。

叢集節點之間通過叢集匯流排連接埠互動資料,使用的協議不同於用戶端的協議,是二進位協議,這可以減少頻寬和處理時間。

Redis叢集資料的分區

Redis叢集不是使用一致性雜湊,而是使用雜湊槽。整個redis叢集有16384個雜湊槽,決定一個key應該分配到那個槽的演算法是:計算該key的CRC16結果再模16834。

叢集中的每個節點負責一部分雜湊槽,比如叢集中有3個節點,則:

  • 節點A儲存的雜湊槽範圍是:0 – 5500
  • 節點B儲存的雜湊槽範圍是:5501 – 11000
  • 節點C儲存的雜湊槽範圍是:11001 – 16384

這樣的分布方式方便節點的添加和刪除。比如,需要新增一個節點D,只需要把A、B、C中的部分雜湊槽資料移到D節點。同樣,如果希望在叢集中刪除A節點,只需要把A節點的雜湊槽的資料移到B和C節點,當A節點的資料全部被移走後,A節點就可以完全從叢集中刪除。

因為把雜湊槽從一個節點移到另一個節點是不需要停機的,所以,增加或刪除節點,或更改節點上的雜湊槽,也是不需要停機的。

如果多個key都屬於一個雜湊槽,叢集支援通過一個命令(或事務, 或lua指令碼)同時操作這些key。通過“雜湊標籤”的概念,使用者可以讓多個key分配到同一個雜湊槽。雜湊標籤在叢集詳細文檔中有描述,這裡做個簡單介紹:如果key含有大括弧”{}”,則只有大括弧中的字串會參與雜湊,比如”this{foo}”和”another{foo}”這2個key會分配到同一個雜湊槽,所以可以在一個命令中同時操作他們。

Redis叢集的主從模式

為了保證在部分節點故障或網路不通時叢集依然能正常工作,叢集使用了主從模型,每個雜湊槽有一(主節點)到N個副本(N-1個從節點)。在我們剛才的叢集例子中,有A,B,C三個節點,如果B節點故障叢集就不能正常工作了,因為B節點中的雜湊槽資料沒法操作。但是,如果我們給每一個節點都增加一個從節點,就變成了:A,B,C三個節點是主節點,A1, B1, C1 分別是他們的從節點,當B節點宕機時,我們的叢集也能正常運作。B1節點是B節點的副本,如果B節點故障,叢集會提升B1為主節點,從而讓叢集繼續正常工作。但是,如果B和B1同時故障,叢集就不能繼續工作了。

Redis叢集的一致性保證

Redis叢集不能保證強一致性。一些已經向用戶端確認寫成功的操作,會在某些不確定的情況下丟失。

產生寫操作丟失的第一個原因,是因為主從節點之間使用了非同步方式來同步資料。

一個寫操作是這樣一個流程:

    1. 1)用戶端向主節點B發起寫的操作
    1. 2)主節點B回應用戶端寫操作成功
    1. 3)主節點B向它的從節點B1,B2,B3同步該寫操作

從上面的流程可以看出來,主節點B並沒有等從節點B1,B2,B3寫完之後再回複用戶端這次操作的結果。所以,如果主節點B在通知用戶端寫操作成功之後,但同步給從節點之前,主節點B故障了,其中一個沒有收到該寫操作的從節點會晉陞成主節點,該寫操作就這樣永遠丟失了。

就像傳統的資料庫,在不涉及到分布式的情況下,它每秒寫回磁碟。為了提高一致性,可以在寫盤完成之後再回複用戶端,但這樣就要損失效能。這種方式就等於Redis叢集使用同步複製的方式。

基本上,在效能和一致性之間,需要一個權衡。

如果真的需要,Redis叢集支援同步複製的方式,通過WAIT指令來實現,這可以讓丟失寫操作的可能性降到很低。但就算使用了同步複製的方式,Redis叢集依然不是強一致性的,在某些複雜的情況下,比如從節點在與主節點失去串連之後被選為主節點,不一致性還是會發生。

這種不一致性發生的情況是這樣的,當用戶端與少數的節點(至少含有一個主節點)網路聯通,但他們與其他大多數節點網路不通。比如6個節點,A,B,C是主節點,A1,B1,C1分別是他們的從節點,一個用戶端稱之為Z1。

當網路出問題時,他們被分成2組網路,組內網路聯通,但2組之間的網路不通,假設A,C,A1,B1,C1彼此之間是聯通的,另一邊,B和Z1的網路是聯通的。Z1可以繼續往B發起寫操作,B也接受Z1的寫操作。當網路恢複時,如果這個時間間隔足夠短,叢集仍然能繼續正常工作。如果時間比較長,以致B1在大多數的這邊被選為主節點,那剛才Z1發給B的寫操作都將丟失。

注意,Z1給B發送寫操作是有一個限制的,如果時間長度達到了大多數節點那邊可以選出一個新的主節點時,少數這邊的所有主節點都不接受寫操作。

這個時間的配置,稱之為節點逾時(node timeout),對叢集來說非常重要,當達到了這個節點逾時的時間之後,主節點被認為已經宕機,可以用它的一個從節點來代替。同樣,在節點逾時時,如果主節點依然不能聯絡到其他主節點,它將進入錯誤狀態,不再接受寫操作。

Redis叢集參數配置
  • cluster-enabled <yes/no>: 如果配置”yes”則開啟叢集功能,此redis執行個體作為叢集的一個節點,否則,它是一個普通的單一的redis執行個體。
  • cluster-config-file <filename>: 注意:雖然此配置的名字叫“叢集設定檔”,但是此設定檔不能人工編輯,它是叢集節點自動維護的檔案,主要用於記錄集群中有哪些節點、他們的狀態以及一些持久化參數等,方便在重啟時恢複這些狀態。通常是在收到請求之後這個檔案就會被更新。
  • cluster-node-timeout <milliseconds>: 這是叢集中的節點能夠失聯的最大時間,超過這個時間,該節點就會被認為故障。如果主節點超過這個時間還是不可達,則用它的從節點將啟動故障遷移,升級成主節點。注意,任何一個節點在這個時間之內如果還是沒有連上大部分的主節點,則此節點將停止接收任何請求。
  • cluster-slave-validity-factor <factor>: 如果設定成0,則無論從節點與主節點失聯多久,從節點都會嘗試升級成主節點。如果設定成正數,則cluster-node-timeout乘以cluster-slave-validity-factor得到的時間,是從節點與主節點失聯後,此從節點資料有效最長時間,超過這個時間,從節點不會啟動故障遷移。假設cluster-node-timeout=5,cluster-slave-validity-factor=10,則如果從節點跟主節點失聯超過50秒,此從節點不能成為主節點。注意,如果此參數配置為非0,將可能出現由於某主節點失聯卻沒有從節點能頂上的情況,從而導致叢集不能正常工作,在這種情況下,只有等到原來的主節點重新迴歸到叢集,叢集才恢複運作。
  • cluster-migration-barrier <count>:主節點需要的最小從節點數,只有達到這個數,主節點失敗時,它從節點才會進行遷移。更詳細介紹可以看本教程後面關於副本遷移到部分。
  • cluster-require-full-coverage <yes/no>:在部分key所在的節點不可用時,如果此參數設定為”yes”(預設值), 則整個叢集停止接受操作;如果此參數設定為”no”,則叢集依然為可達節點上的key提供讀操作。
建立和使用Redis叢集

要建立叢集,首先需要以叢集模式啟動並執行空redis執行個體。也就說,以普通模式啟動的redis是不能作為叢集的節點的,需要以叢集模式啟動的redis執行個體才能有叢集節點的特性、支援叢集的指令,成為叢集的節點。

下面是最小的redis叢集的設定檔:

port 7000cluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000appendonly yes

開啟叢集模式只需開啟cluster-enabled配置項即可。每一個redis執行個體都包含一個設定檔,預設是nodes.conf,用於儲存此節點的一些配置資訊。這個設定檔由redis叢集的節點自行建立和更新,不能由人手動地去修改。

一個最小的叢集需要最少3個主節點。第一次測試,強烈建議你配置6個節點:3個主節點和3個從節點。

開始測試,步驟如下:先進入新的目錄,以redis執行個體的連接埠為目錄名,建立目錄,我們將在這些目錄裡運行我們的執行個體。

類似這樣:

mkdir cluster-testcd cluster-testmkdir 7000 7001 7002 7003 7004 7005

在7000-7005的每個目錄中建立設定檔redis.conf,內容就用上面的最簡配置做模板,注意修改連接埠號碼,改為跟目錄一致的連接埠。

把你的redis伺服器(用GitHub中的不穩定分支的最新的代碼編譯來)拷貝到cluster-test目錄,然後開啟6個終端頁準備測試。

在每個終端啟動一個redis執行個體,指令類似這樣:

cd 7000../redis-server ./redis.conf

在日誌中我們可以看到,由於沒有nodes.conf檔案不存在,每個節點都給自己一個新的ID。

[82462] 26 Nov 11:56:55.329 * No cluster configuration found, I‘m 97a3a64667477371c4479320d683e4c8db5858b1

這個ID將一直被此節點使用,作為此節點在整個叢集中的唯一標識。節點區分其他節點也是通過此ID來標識,而非IP或連接埠。IP可以改,連接埠可以改,但此ID不能改,直到這個節點離開叢集。這個ID稱之為節點ID(Node ID)。

建立叢集

現在6個執行個體已經運行起來了,我們需要給節點寫一些有意義的配置來建立叢集。redis叢集的命令工具redis-trib可以讓我們建立叢集變得非常簡單。redis-trib是一個用ruby寫的指令碼,用於給各節點髮指令建立叢集、檢查叢集狀態或給叢集重新分區等。redis-trib在Redis源碼的src目錄下,需要gem redis來運行redis-trib。

gem install redis

建立叢集只需輸入指令:

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

這裡用的命令是create,因為我們需要建立一個新的叢集。選項”–replicas 1”表示每個主節點需要一個從節點。其他參數就是需要加入這個叢集的redis執行個體的地址。

我們建立的叢集有3個主節點和3個從節點。

redis-trib會給你一些配置建議,輸入yes表示接受。叢集會被配置並彼此串連好,意思是各節點執行個體被引導彼此通話並最終形成叢集。最後,如果一切順利,會看到類似下面的資訊:

[OK] All 16384 slots covered

這表示,16384個雜湊槽都被主節點正常服務著。

使用create-cluster指令碼建立redis叢集

如果你不想像上面那樣,單獨的手工配置各節點的方式來建立叢集,還有一個更簡單的系統(當然也沒法瞭解到叢集運作的一些細節)。

在utils/create-cluster目錄下,有一個名為create-cluster的bash指令碼。如果需要啟動一個有3個主節點和3個從節點的叢集,只需要輸入以下指令

1. create-cluster start
2. create-cluster create

在步驟2,當redis-trib要你接受叢集的布局時,輸入”yes”。

現在你可以跟叢集互動,第一個節點的開始端點口預設是30001。當你完成後,停止叢集用如下指令:

1. create-cluster stop.

請查看目錄下的README,它有詳細的介紹如何使用此指令碼。

試用一下叢集

可以用上面提供的用戶端或redis-cli命令來測試叢集。

下面用redis-cli來作為例子測試:

$ redis-cli -c -p 7000redis 127.0.0.1:7000> set foo bar-> Redirected to slot [12182] located at 127.0.0.1:7002OKredis 127.0.0.1:7002> set hello world-> Redirected to slot [866] located at 127.0.0.1:7000OKredis 127.0.0.1:7000> get foo-> Redirected to slot [12182] located at 127.0.0.1:7002"bar"redis 127.0.0.1:7000> get hello-> Redirected to slot [866] located at 127.0.0.1:7000"world"

注意:如果你用指令碼來建立的叢集,你的redis可能監聽在不同的連接埠,預設是從30001開始。

redis-cli利用叢集的任意節點會告知用戶端正確節點的特性,實現了叢集用戶端的最基礎功能。實現得比較嚴謹的用戶端可以緩衝雜湊槽到節點的映射關係,讓用戶端直接連接到正確的節點,只有叢集的節點配置有更新時才重新整理緩衝,比如發生了故障遷移,或者管理員增加或減少了節點等。

重新分區

重新分區簡單的說就是把雜湊槽從一些節點移動到另外一些節點。重新分區可以像建立叢集一樣,使用redis-trib來完成。

開始重新分區,輸入以下指令:

./redis-trib.rb reshard 127.0.0.1:7000

你只需要指定叢集中的一個節點,redis-trib會自動找到叢集中的其他節點。

目前,redis-trib只支援管理員操作,不能夠說:移動50%的雜湊槽從這個節點到那個節點。它以問問題的方式開始。第一個問題是,你需要重新分區多少個雜湊槽:

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

由於我們之前的指令碼一直在運行,而且沒有用sleep調用,這時候應該已經插入了比較多的key了。我們可以嘗試給1000個雜湊槽重新分區。

然後,redis-trib需要知道我們要把這1000個雜湊槽移動到哪個節點去,也就是接受這1000個雜湊槽的節點。我想用127.0.0.1:7000這個節點。需要用節點ID來告知redis-trib是哪個節點。redis-trib已經在螢幕上列出了所有的節點和他們的ID。也可以通過以下命令找到指定節點的ID:

$ redis-cli -p 7000 cluster nodes | grep myself97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master - 0 0 0 connected 0-5460

好了,我的目標節點是97a3a64667477371c4479320d683e4c8db5858b1。

現在redis-trib會問:你想從哪些節點中挪走這些雜湊槽呢?我輸入all,會從其他的主節點中挪走雜湊槽。

在輸入最後確認之後,redis-trib在螢幕上會輸出每一個雜湊槽將從哪個節點轉移到哪個節點。每實際移動一個key螢幕就會列印一個點。

在重新分區的過程中,你可以看到,你剛才啟動並執行指令碼不受影響,你甚至可以在重新分區的過程中,反覆的重新運行該例子指令碼。

在重新分區結束後,你可以檢查叢集的目前狀態是否正常,運行下面的命令:

./redis-trib.rb check 127.0.0.1:7000

所有的雜湊槽都存在,這時候127.0.0.1:7000的主節點有多一點的雜湊槽,有大概6461個。

指令碼化重新分區

重新分區可以不用以互動的方式進行,使用下面的指令可以自動執行:

./redis-trib.rb reshard --from <node-id> --to <node-id> --slots <number of slots> --yes <host>:<port>

如果你想要經常的重新分區,可以使用上面的指令自動分區,但是目前redis-trib指令碼不會根據節點上的key的分布來做負載平衡、智能地遷移雜湊槽。這個特性在將來我們會添加的。

測試故障遷移

注意:測試過程中,請讓上面的一致性測試的應用程式一直運行中。
為了觸發故障遷移,最簡單的辦法是讓一個進程宕機,在我們的用例中,就是讓其中一個主節點進程宕機。
我們可以用下面的指令區分叢集節點:

$ redis-cli -p 7000 cluster nodes | grep master3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385482984082 0 connected 5960-109212938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 master - 0 1385482983582 0 connected 11423-1638397a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master - 0 0 0 connected 0-5959 10922-11422

所以,7000,7001,7002是主節點,我們要使7002當機,使用DEBUG SEGFAULT指令:

$ redis-cli -p 7002 debug segfaultError: Server closed the connection現在,我們看看剛才那個一致性檢測器的例子輸出了什麼: 
18849 R (0 err) | 18849 W (0 err) |23151 R (0 err) | 23151 W (0 err) |27302 R (0 err) | 27302 W (0 err) |... many error warnings here ...29659 R (578 err) | 29660 W (577 err) |33749 R (578 err) | 33750 W (577 err) |37918 R (578 err) | 37919 W (577 err) |42077 R (578 err) | 42078 W (577 err) |

我們看到,例子顯示有578個讀失敗和577個寫失敗,但沒有不一致性產生。我們前面的章節提到過,redis叢集不是強一致性的,由於它非同步複製資料到從節點,可能會在主節點失敗的情況下導致資料丟失,但是上面的例子顯示沒有不一致性產生,為什麼呢?因為主節點響應用戶端後馬上同步資料給從節點,這幾乎是同時的,這裡的時間差非常小,只有在這個非常小的時間差中主節點故障,才會發生不一致性。儘管發生的可能性很小,不代表它不可能發生,redis叢集依然不是強一致性的。
現在我們看看當該節點故障之後,叢集做了什麼(注意,我已經重啟了該故障的節點,它已經重新連上叢集,並成為了從節點):

$ redis-cli -p 7000 cluster nodes3fc783611028b1707fd65345e763befb36454d73 127.0.0.1:7004 slave 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 0 1385503418521 0 connecteda211e242fc6b22a9427fed61285e85892fa04e08 127.0.0.1:7003 slave 97a3a64667477371c4479320d683e4c8db5858b1 0 1385503419023 0 connected97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master - 0 0 0 connected 0-5959 10922-114223c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7005 master - 0 1385503419023 3 connected 11423-163833e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385503417005 0 connected 5960-109212938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385503418016 3 connected

現在,主節點的連接埠變成了:7000,7001,7005(之前主節點是7002的,現在變成主節點是7005了)。
“cluster nodes”指令的輸出看起來蠻嚇人的,其實很簡單,它的每列意義如下:

*節點ID
*IP:連接埠
*標記位:主節點,從節點,自己,失敗。。。
*如果是從節點,則接下來是它的主節點的ID
*最後一次發送ping依然等待響應的時間
*最後一次收到pong的時間
*上次更新此配置的時間
*節點的串連狀態
*儲存的雜湊槽

手動容錯移轉

有時候,手動容錯移轉是非常有用的,它不會給主節點帶來任何問題,比如,需要升級某個主節點的redis進程,可以先通過手動容錯移轉使之成為從節點,讓升級對叢集可用性的影響達到最低。
redis叢集支援通過指令”CLUSTER FAILOVER”產生容錯移轉,但需要在被失效的主節點的一個從節點上執行該命令。
相對於真的主節點宕機,手動容錯移轉是比較安全的,它可以避免資料丟失,當新的主節點複製完所有資料之後,會讓用戶端從原來的主節點重新導向到新的主節點。
下面是在其中一個從節點上執行了cluster failover指令之後看到的一些日誌:

# Manual failover user request accepted.# Received replication offset for paused master manual failover: 347540# All master replication stream processed, manual failover can start.# Start of election delayed for 0 milliseconds (rank #0, offset 347540).# Starting a failover election for epoch 7545.# Failover election won: I‘m the new master.

簡單的說:用戶端停止串連被容錯移轉的原主節點;同時該原主節點把還沒同步的複製集同步給從節點;當從節點收到所有複製集之後,容錯移轉開始,原來主節點被通知配置更新,主節點更換了;用戶端被重新導向到新的主節點。

新增新的節點

新增一個節點,就增加一個空的節點到叢集。有兩種情況:如果新增的是主節點,則是從叢集的其他節點中轉移部分資料給它;如果新增的是從節點,則告訴它從一個已知的節點中同步複製集。

我們2種情況都試試。首先是新增一個新的主節點到叢集中。
兩種情況,都是需要先加入一個空的節點到叢集中

鑒於我們前面已經啟動了6個節點,連接埠號碼7000-7005已經用了,新增節點的連接埠號碼就用7006吧。新增一個新的空節點,就跟上面啟動前面6個節點的步驟一樣(記得改設定檔的連接埠號碼):

    1. *在終端開啟一個新的頁面
    1. *進入到cluster-test目錄
    1. *建立名為“7006”的目錄
    1. *在該目錄下建立redis.conf檔案,內容跟其他節點的內容一致,只是連接埠號碼改成7006.
    1. *最後啟動它:../redis-server ./redis.conf

現在該節點應該運行起來了。
現在,我們使用redis-trib來增加一個新節點到叢集中:

./redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000

使用add-node指令來新增節點,第一個地址是需要新增的節點地址,第二個地址是叢集中任意一個節點地址。
redis-trib指令碼只是給發送CLUSTER MEET訊息給節點,這也可以手動地通過用戶端發送,但redis-trib在發送之前會檢查叢集的狀態,所以,還是用redis-trib指令碼來操作叢集會比較好。
現在我們可以連上新的節點,看看它是不是已經加入叢集了:

redis 127.0.0.1:7006> cluster nodes3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385543178575 0 connected 5960-109213fc783611028b1707fd65345e763befb36454d73 127.0.0.1:7004 slave 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 0 1385543179583 0 connectedf093c80dde814da99c5cf72a7dd01590792b783b :0 myself,master - 0 0 0 connected2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385543178072 3 connecteda211e242fc6b22a9427fed61285e85892fa04e08 127.0.0.1:7003 slave 97a3a64667477371c4479320d683e4c8db5858b1 0 1385543178575 0 connected97a3a64667477371c4479320d683e4c8db5858b1 127.0.0.1:7000 master - 0 1385543179080 0 connected 0-5959 10922-114223c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7005 master - 0 1385543177568 3 connected 11423-16383

雖然現在此新節點已經連到叢集,並且可以重新導向用戶端到正確的叢集節點了,但是它跟叢集的其他主節點有個不同的地方:
*它沒有資料,因為沒有分配雜湊槽給它
*因為它是一個沒有雜湊槽的主節點,當一個從節點需要被選舉成新主節點時,它沒有參與權

可以通過redis-trib的重新分區指令來給新節點增加雜湊槽。由於前面已經介紹過如何重新分區了,這裡就不做詳細介紹。

添加一個從節點

新增從節點有兩種方法,第一個是使用上面的redis-trib指令碼,增–slave選項,類似這樣:

./redis-trib.rb add-node --slave 127.0.0.1:7006 127.0.0.1:7000

注意到上面的命令列跟我們加主節點的命令列類似,所以沒有沒有指定新增的從節點的主節點是哪個,這時候redis-trib會在擁有最少從節點的主節點中隨機選一個作為新增節點的主節點。
當然也可以通過如下的命令指定新增從節點的主節點:

./redis-trib.rb add-node --slave --master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7006 127.0.0.1:7000

用上面的指令,我們可以指定新的從節點是那個主節點的複本集。

另一個方法,先把新節點以主節點的形式加入到叢集,然後再用“CLUSTER REPLICATE”指令把它變為從節點。這個方式也適用於給從節點更換主節點。
比如,已有主節點127.0.0.1:7005,它儲存的雜湊槽範圍是11423-16383,節點ID為3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e,我們希望給它新增從節點。首先用之前的方法新增一個空的主節點,然後連上該新節點,發送如下指令:

redis 127.0.0.1:7006> cluster replicate 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e

這樣,新的從節點添加成功,而且叢集中其他所有節點都已經知道新節點了(可能需要一些時間來更新配置)。我們可以通過以下指令來驗證:

$ redis-cli -p 7000 cluster nodes | grep slave | grep 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912ef093c80dde814da99c5cf72a7dd01590792b783b 127.0.0.1:7006 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385543617702 3 connected2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385543617198 3 connected

現在節點3c3a0c…有2個從節點,分別是原來的運行在7002連接埠的節點和剛剛新增的7006連接埠的節點。

刪除節點

使用redis-trib的指令”del-node”可以刪除節點:

./redis-trib del-node 127.0.0.1:7000 `node-id`

第一個參數是叢集的任意一個節點,第二個參數是需要刪除的節點的ID。
同樣的方法可以刪除主節點,但是在刪除之前,需要通過重新分區把資料都移走。
另一個刪除主節點的方式是通過手動容錯移轉,讓它的其中一個從節點升級成主節點後再把此節點刪除。但這樣並不會減少叢集的主節點數,如果需要減少主節點數,重新分區在所難免。

複製集遷移

在redis叢集中,可以通過如下指令,在任意時間給從節點更換主節點:

CLUSTER REPLICATE <master-node-id>

有一種特殊的情境:系統自動地更改複製集的主節點,而不是要管理員手動處理。這種自動重新設定從節點的情景叫複本集遷移(replicas migration),它可以增加redis叢集的健壯性。

注意:你可以通過《Redis Cluster Specification》瞭解更多詳細的內容,這裡只是對它的簡單介紹以及它的用處。

假如一個每個主節點只有一個從節點的叢集,在一個主節點和從節點同時故障的情況下,叢集將不能繼續工作,因為已經故障的節點中儲存的雜湊槽資料已經沒法讀寫。雖然網路斷開很可能會讓一大批節點同時被隔離,但是還有很多其他情況會導致節點故障,比如硬體或者軟體的故障導致一個節點宕機,也是非常重要的導致節點故障的原因,這種情況一般不會所有節點同時故障。比如,叢集中每個主節點都有一個從節點,在4點的時候一個從節點被kill,該主節點在6點被kill。這樣依然會導致叢集不能工作。

為了增強系統的可用性,可以給每個主節點再增加一個從節點,但這樣做是比較昂貴的。複製集遷移可以讓我們只給部分主節點增加多些從節點。比如有10個主節點,每個主節點有1個從節點,總共20個節點,然後可以再增加一些從節點(比如3個從節點)到一些主節點,這樣就有部分主節點的從節點數超過1。

當一個主節點沒有從節點時,如果叢集中存在一個主節點有多個從節點時,複製集遷移機制在這些多個從節點中找一個節點,給沒有從節點的主節點做複製集。所以當4點鐘一個從節點宕機,另一個從節點將會代替它成為該主節點的從節點;然後在5點鐘主節點宕機時還有一個從節點可以升級成主節點,這樣叢集可以繼續運行。

所以,簡單的說複本集遷移就是:
*叢集會找到擁有最多從節點的主節點,在它的從節點中挑選一個,進行複製集遷移
*為了讓複製集遷移生效,只需要在叢集中多加幾個從節點,隨便加到哪個主節點都可以
*關於複製集遷移,有一個配置參數叫“cluster-migration-barrier”,在叢集的樣板設定檔中有詳細說明,需要瞭解清楚

升級叢集中的節點

升級從節點非常簡單,只要停止它再重啟更新過的版本即可。如果用戶端連到了從節點,在該節點不可用時,用戶端需要重連到另外可用的從節點上。

升級主點則相對複雜,下面是推薦的流程:
1. 使用CLUSTER FAILOVER指令觸發手動容錯移轉,讓主節點變成從節點
2. 等到主節點成為從節點
3.升級該從節點
4. 如果你想讓升級過的節點重新變成主節點,則再次觸發手動容錯移轉,讓它變成新的主節點。

用這樣的步驟,一個個的升級所有節點。

遷移到redis叢集

使用者需要把redis的資料移轉到redis叢集,原來的資料可能是只有一個主節點,也可能是用已有的方式分區過,key被儲存在N個幾節點中。

上面2中情況都很容易遷移,特別重要的細節是是否使用了多個key以及是如何使用多個key的。下面是3種不同的情況:
1. 沒有操作多個key(包括操作多個key的指令、事務、lua指令碼)。所有key都是獨立操作的.
2. 操作了多個key(包括操作多個key的指令、事務、lua指令碼),但這些key都有相同的雜湊標籤,比如這些被同時操作的key:SUNION{user:1000}.foo {user:1000}.bar
3. 操作了多個key(包括操作多個key的指令、事務、lua指令碼),這些key沒有特別處理,也沒有相同標籤。

第三種情況redis叢集沒法處理,需要修改應用程式,不要使用多個key,或者給這些key加上相同的雜湊標籤。

第一和第二種情況可以處理,而且他們的處理方式一樣。

假設你已有的資料被分成N個主節點儲存(當N=1時,就是沒有分區的情況),要把資料移轉到redis叢集,需要執行下面幾個步驟:
1. 停止你的用戶端。目前沒有自動線上遷移到redis叢集的方法。你可以自己策劃如何讓你的應用程式支援線上遷移。
2. 使用BGREWRITEAOF指令讓所有主節點產生AOF檔案,並且等待這些檔案建立完成。
3. 把這些AOF檔案儲存下來,分別命名為aof-1, aof-2, ..aof-N,如果需要,可以停止原來的redis執行個體(對於非虛擬化部署,需要重用這台電腦來說,把舊進程停掉很有協助)。
4. 建立N個主節點+0個從節點的redis叢集。晚些時候再添加從節點。請確認所有節點都開啟了appendonly的配置。
5. 停止叢集的所有節點,然後用剛才儲存的AOF檔案,代替每個節點的AOF檔案,aof-1給第一個節點,aof-2給第二個節點,以此類推。
6. 重啟所有節點,這些節點可能會提示說根據配置有些key不應該儲存在這個節點。
7. 使用redis-trib fix指令,讓叢集自動根據雜湊槽遷移資料
8. 使用redis-trib check指令確保你的叢集是正常的
9. 讓你的用戶端使用redis叢集用戶端庫,並重啟它。

還有一個方法可以從已有的redis執行個體中匯入資料到redis叢集,使用redis-trib import指令。該指令會把源執行個體中的資料都刪除,並把資料寫入事先部署好的叢集中。需要注意的是,如果你的源執行個體使用的是redis2.8版本,這個匯入處理程序可能會比較長,因為2.8版本沒有實現資料移轉的串連緩衝,所以最好把源執行個體的redis版本先升級到3.x的版本。

Redis叢集知識解析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.