Redis集群·Redis集群提供了一種運行Redis安裝的方法,在該安裝中,數(shù)據(jù)會在多個Redis節(jié)點之間自動分片。 Redis集群在分區(qū)期間還提供了一定程度的可用性,這實際上是在某些節(jié)點出現(xiàn)故障或無法通信時有繼續(xù)工作的能力。但是,如果發(fā)生較嚴重故障(例如,大多數(shù)主節(jié)點不可用時),集群將停止運行。 實際上,Redis集群能給你帶來什么?
Redis集群TCP端口每個Redis集群節(jié)點都需要打開兩個TCP連接。用于服務(wù)客戶端的常規(guī)RedisTCP端口,例如 第二個值更大一點的端口用于集群總線,也就是使用二進制協(xié)議的節(jié)點到節(jié)點之間的通信通道。節(jié)點將集群總線用于故障檢測,配置更新,故障轉(zhuǎn)移授權(quán)等??蛻舳擞肋h不要嘗試與集群總線端口進行通信,而應(yīng)始終與普通的Redis命令端口進行通信,但是請確保您在防火墻中同時打開了這兩個端口,否則Redis集群節(jié)點將無法進行通信。 命令端口和集群總線端口的偏移量是固定的,并且始終為 請注意,對于每個節(jié)點,要使Redis集群正常工作,您需要:
如果您沒有同時打開兩個TCP端口,則集群將無法正常工作。 集群總線使用不同的二進制協(xié)議進行節(jié)點到節(jié)點的數(shù)據(jù)交換,它更適合于在節(jié)點之間使用較少的帶寬和較少的處理時間來交換信息。 Redis集群數(shù)據(jù)分片Redis集群不使用一致性哈希,而是使用一種不同形式的分片,從概念上講每個key都是我們稱為hash槽的一部分。 Redis集群中有16384個hash槽,要計算給定key的hash槽,需將key的CRC16值用16384取模。 Redis集群中的每個節(jié)點都負責(zé)hash槽的子集,例如,您可能有一個包含3個節(jié)點的集群,其中:
這樣可以輕松添加和刪除集群中的節(jié)點。例如,如果我想添加一個新節(jié)點D,則需要將一些hash槽從節(jié)點A,B,C移到D。類似地,如果我想從集群中刪除節(jié)點A,則只需移動A所服務(wù)的hash槽到B和C。當(dāng)節(jié)點A為空時,我可以將其從集群中完全刪除。 因為將hash槽從一個節(jié)點移動到另一個節(jié)點不需要停止操作,所以添加刪除節(jié)點或更改節(jié)點服務(wù)的hash槽的百分比不需要停機。 只要單個命令執(zhí)行(或整個事務(wù)或Lua腳本執(zhí)行)中涉及的所有key都屬于同一個hash槽,Redis集群就支持多key操作。用戶可以通過使用稱為hash標(biāo)簽的概念來強制多個key成為同一hash槽的一部分。 hash標(biāo)簽記錄在Redis集群規(guī)范中,注意,如果key的{}中的括號之間有一個子字符串,則僅對字符串中的內(nèi)容進行hash處理,例如,一個叫{foo}的key和另一個叫{foo} 的 key保證在同一hash槽中,并且可以在以多個key作為參數(shù)的命令中一起使用。 Redis集群主備模式為了在主節(jié)點子集發(fā)生故障或無法與大多數(shù)節(jié)點通信時保持可用,Redis集群使用主備模型,其中每個hash槽具有從1(主節(jié)點本身)到N個副本(N -1個其他備份節(jié)點)。 在一個包含節(jié)點A,B,C的集群中,如果節(jié)點B失敗,則集群將無法繼續(xù),因為我們不能為 5501-11000 范圍內(nèi)的hash槽提供服務(wù)。但是,在創(chuàng)建集群(或稍后)時,我們向每個主節(jié)點添加一個備份節(jié)點,以便最終集群由作為主節(jié)點的A,B,C和作為備份節(jié)點的A1,B1,C1組成 ,如果節(jié)點B發(fā)生故障,系統(tǒng)將能夠持續(xù)運行。節(jié)點B1復(fù)制B,并且B發(fā)生故障,集群會將節(jié)點B1提升為新的主節(jié)點,并將繼續(xù)正常運行。 但是請注意,如果節(jié)點B和B1同時失敗,則Redis集群無法繼續(xù)運行。 Redis集群的一致性保證Redis集群無法保證強一致性。 實際上,這意味著在某些情況下,Redis集群可能會丟失系統(tǒng)給客戶端的已經(jīng)確認的寫操作。 Redis集群可能丟失寫入的第一個原因是因為它使用異步復(fù)制。這意味著在寫入期
如您所見,B在回復(fù)客戶端之前不會等待B1,B2,B3的確認,因為這會對Redis造成延遲,因此,如果您的客戶端進行了寫操作,然后B會確認,但是在它把寫操作發(fā)送給備份節(jié)點之前崩潰了,此時其中一個備份節(jié)點(未接收到寫操作)可以升級為主節(jié)點,這樣就永遠丟失該寫操作。這與配置為每秒將數(shù)據(jù)刷新到磁盤的大多數(shù)數(shù)據(jù)庫所發(fā)生的情況非常相似,因此由于過去使用不涉及分布式系統(tǒng)的傳統(tǒng)數(shù)據(jù)庫系統(tǒng)的經(jīng)驗,您已經(jīng)可以對此進行合理推斷。同樣,您可以通過強制數(shù)據(jù)庫在答復(fù)客戶端之前刷新磁盤上的數(shù)據(jù)來提高一致性,但這通常會導(dǎo)致性能過低。在Redis集群下,這相當(dāng)于同步復(fù)制。 基本上,在性能和一致性之間進行權(quán)衡是必須的。 Redis集群在需要時可以通過WAIT命令實現(xiàn)同步寫,這使得丟失寫的可能性大大降低,但是請注意,即使使用同步復(fù)制,Redis集群也不實現(xiàn)強一致性:在更復(fù)雜的情況下,總是有可能存在一種場景,就是一個無法接收數(shù)據(jù)的備份節(jié)點被選為主節(jié)點。 還有一種值得注意的情況,Redis集群也會丟失寫操作,這種情況發(fā)生在網(wǎng)絡(luò)分區(qū)期間,在該分區(qū)中,客戶端與少數(shù)實例(至少包括主節(jié)點)隔離。 以我們的6個節(jié)點集群為例,該集群由A,B,C,A1,B1,C1組成,具有3個主節(jié)點 發(fā)生分區(qū)后,可能在分區(qū)的一側(cè)有A,C,A1,B1,C1,而在另一側(cè)有B和Z1。 Z1仍然能夠?qū)進行寫操作,B將接受其寫入。如果分區(qū)在很短的時間內(nèi)恢復(fù)正常,則集群將繼續(xù)正常運行。但是,如果分區(qū)持續(xù)的時間足以使B1升級為該分區(qū)的多數(shù)端的主節(jié)點,則Z1向B發(fā)送的寫操作將丟失。 請注意,Z1將能夠發(fā)送到B的寫入量有一個最大的窗口:如果已經(jīng)有足夠的時間使大分區(qū)選舉出一個主節(jié)點,則小分區(qū)中的每個主節(jié)點都將停止接受寫入。該時間是Redis集群的一個非常重要的配置指令,稱為節(jié)點超時。 在節(jié)點超時之后,主節(jié)點被視為發(fā)生故障,并且可以用其副本之一替換。類似地,在超過指定的時間后,主節(jié)點還是無法感知大多數(shù)其他主節(jié)點,此主節(jié)點進入錯誤狀態(tài)并停止接受寫入。 Redis集群配置參數(shù)我們將創(chuàng)建一個集群部署作為例子。在繼續(xù)之前,讓我們介紹一下Redis集群里的redis.conf文件中引入的配置參數(shù)。
創(chuàng)建和使用一個Redis集群注意:手動部署Redis集群,了解其某些操作非常重要。 但是,如果要盡快建立集群并運行,請?zhí)^本節(jié)和下一節(jié),直接轉(zhuǎn)到使用 create-cluster 腳本創(chuàng)建Redis集群。 要創(chuàng)建集群,我們需要做的第一件事就是讓一些空Redis實例運行在集群模式下?;旧希@意味著不能使用常規(guī)Redis實例來創(chuàng)建集群,因為需要配置特殊模式,以便Redis實例啟用集群特定的功能和命令。 以下是最小的Redis集群配置文件:
啟用集群模式的只需要直接打開cluster-enabled命令。每個實例還包含該節(jié)點配置存儲位置的文件路徑,默認情況下為nodes.conf。 該文件不會被人接觸。 它只是由Redis集群實例在啟動時生成,并在需要時進行更新。 請注意,按預(yù)期工作的最小集群要求至少包含三個主節(jié)點。 對于您的第一個測試,強烈建議啟動一個包含三個主節(jié)點和三個備份節(jié)點的六個節(jié)點集群。為此,輸入一個新目錄并創(chuàng)建以下目錄,該目錄以我們將在給定目錄中運行的實例的端口號命名。就像是:
在從7000到7005的每個目錄中創(chuàng)建一個redis.conf文件。作為配置文件的模板,只需使用上面的小示例,但請確保根據(jù)目錄名稱用正確的端口號替換端口號7000。現(xiàn)在,將您的redis-server可執(zhí)行文件(從GitHub不穩(wěn)定分支中的最新資源編譯而來)復(fù)制到cluster-test目錄中,最后在您喜歡的終端應(yīng)用程序中打開6個終端選項卡。 像這樣啟動每個實例,每個選項卡一個:
從每個實例的日志中可以看到,由于不存在nodes.conf文件,因此每個節(jié)點都會為其分配一個新的ID。
該ID將由該實例永久使用,以使該實例在集群的上下文中具有唯一的名稱。每個節(jié)點都使用該ID而不是IP或端口記住其他每個節(jié)點。 IP地址和端口可能會更改,但是唯一的節(jié)點標(biāo)識符在節(jié)點的整個生命周期中都不會改變。我們將此標(biāo)識符簡稱為節(jié)點ID。 創(chuàng)建集群現(xiàn)在,我們有許多實例正在運行,然后需要通過向節(jié)點寫入一些有意義的配置來創(chuàng)建集群。 如果您使用的是Redis 5,這很容易完成,這是因為redis-cli中嵌入了Redis集群命令行實用程序,我們可以使用它來創(chuàng)建新集群,檢查或重新分片現(xiàn)有集群等。 對于Redis版本3或4,有一個稱為redis-trib.rb的較老的工具,它非常相似。您可以在Redis源代碼分發(fā)的src目錄中找到它。 您需要安裝redis gem才能運行redis-trib。
第一個示例,即集群創(chuàng)建,將在Redis 5中使用redis-cli以及在Redis 3和4中使用redis-trib來顯示。但是,接下來的所有示例都將僅使用redis-cli,因為您可以看到他們語法非常相似,您也可以使用redis-trib.rb help來獲取有關(guān)語法的信息,從而將一個命令行簡單地更改為另一命令行。 重要:請注意,如果需要,可以對Redis 4集群使用Redis 5 redis-cli。 要使用redis-cli為Redis 5創(chuàng)建集群,只需鍵入:
對于redis 4或者3 請使用redis-trib.rb工具:
此處使用的命令是create,因為我們要創(chuàng)建一個新集群。 選項 顯然,滿足我們要求的唯一設(shè)置是創(chuàng)建具有3個主節(jié)點和3個從節(jié)點的集群。 Redis-cli將為您提供配置。 鍵入yes,將接受建議的配置。集群將被配置并加入,這意味著實例將被啟動然后彼此
意思就是說至少有一個主節(jié)點實例服務(wù)于16384個槽位中某一個. 使用create-cluster腳本創(chuàng)建一個Redis集群如果您不想如上所述通過手動配置和執(zhí)行單個實例來創(chuàng)建Redis集群,則可以使用更簡單的系統(tǒng)(但是您將不會學(xué)到同樣多的操作細節(jié))。 只需檢查Redis發(fā)行版中的utils / create-cluster目錄。內(nèi)部有一個名為create-cluster的腳本(名稱與包含在其中的目錄相同),它是一個簡單的bash腳本。 為了啟動具有3個主節(jié)點和3個備份節(jié)點的6節(jié)點集群,只需鍵入以下命令:
在步驟2中,當(dāng)redis-cli希望您接受集群布局時,回復(fù)yes。 現(xiàn)在,您可以與集群進行交互,默認情況下,第一個節(jié)點將從端口30001開始。 完成后,使用以下命令停止集群:
關(guān)于如何運行這個腳本的更多信息,請閱讀目錄里的README。 集群操作到目前為止,Redis集群的問題之一是缺少客戶端庫的實現(xiàn)。 據(jù)我所知有以下實現(xiàn):
測試Redis集群的一種簡單方法是嘗試上述任何客戶端,或者僅嘗試redis-cli命令。以下是使用后者進行交互的示例:
注意:如果使用腳本創(chuàng)建集群,則節(jié)點可能會偵聽不同的端口,默認情況下從30001開始。 redis-cli的支持非?;A(chǔ),因此它始終基于以下事實:Redis集群節(jié)點能夠?qū)⒖蛻舳酥囟ㄏ虻秸_的節(jié)點。一個嚴格的客戶端可以做得更好,并且可以在hash槽和節(jié)點地址之間緩存映射,以便直接使用與節(jié)點的正確連接。僅在集群配置中發(fā)生某些更改時(例如,在故障轉(zhuǎn)移之后或系統(tǒng)管理員通過添加或刪除節(jié)點來更改集群布局之后),才會刷新映射。 使用redis-rb-cluster寫一個簡單的應(yīng)用程序在繼續(xù)展示如何操作Redis集群之前,比如執(zhí)行故障轉(zhuǎn)移或重新分片之類的操作,我們需要創(chuàng)建一些示例應(yīng)用程序,或者至少要能夠理解簡單的Redis集群客戶端交互的語義。 通過這種方式,我們可以運行一個示例,同時嘗試使節(jié)點發(fā)生故障或開始重新分片,以了解Redis集群在現(xiàn)實環(huán)境下的行為。只是觀察一個沒有寫入任何數(shù)據(jù)的集群是沒有幫助的。 本節(jié)說明了redis-rb-cluster的一些基本用法,其中顯示了兩個示例。 首先是以下內(nèi)容,它是redis-rb-cluster發(fā)行版中的example.rb文件:
該程序做了一件非常簡單的事情,它將foo
該程序看起來比較復(fù)雜,因為它需要在屏幕上顯示錯誤而不是異常退出,因此,對集群執(zhí)行的每個操作都應(yīng)該由錯誤處理包裝。 第14行是程序中的第一個有趣的行。它創(chuàng)建Redis集群對象,使用啟動節(jié)點列表作為參數(shù),并允許該對象與不同節(jié)點建立的最大連接數(shù),最后是超時時間,對于給定的操作多少時間后被視為失敗。 啟動節(jié)點不需要是集群的所有節(jié)點。但至少有一個節(jié)點是可達的。還要注意,只要能夠與第一個節(jié)點連接,redis-rb-cluster就會更新此啟動節(jié)點列表。您應(yīng)該期望任何其他嚴格的客戶端都應(yīng)該采取這種行為。 現(xiàn)在我們已經(jīng)將Redis集群對象實例存儲在rc變量中,我們可以像使用普通的Redis對象實例一樣使用該對象了。 這恰好發(fā)生在第18至26行中:重新啟動示例時,我們不想以foo0重新開始,因此我們將計數(shù)器存儲在Redis本身內(nèi)。上面的代碼旨在讀取此計數(shù)器,或者如果不存在該計數(shù)器,則為其分配零值。 但是請注意這是一個while循環(huán),因為即使集群關(guān)閉并返回錯誤,我們也要一次又一次嘗試。普通的應(yīng)用程序不需要那么小心。 28和37之間開始主循環(huán),在該循環(huán)中設(shè)置key或顯示錯誤。 注意循環(huán)結(jié)束時的sleep調(diào)用。在測試中,如果您想盡可能快地寫入集群,則可以刪除sleep(相對來說,這只是一個很繁忙的循環(huán)操作,它并沒有真正的并行,因此,在最好的條件下,您通常將獲得每秒10k個操作))。 通常,為了使示例程序更容易被人看懂,寫入速度會減慢。啟動應(yīng)用程序?qū)a(chǎn)生以下輸出:
這不是一個非常有趣的程序,我們稍后將使用更好的程序,但是我們已經(jīng)可以看到程序運行時,在重新分片期間都發(fā)生了什么。 集群重新分片現(xiàn)在,我們準備嘗試集群重新分片。 為此,請保持example.rb程序運行,以便您查看對程序的運行是否有影響。另外,您可能想注釋一下sleep調(diào)用,以便在重新分片期間發(fā)生一些更嚴重的寫入負載。重新分片基本上意味著將hash槽從一組節(jié)點移動到另一組節(jié)點,并且像集群創(chuàng)建一樣,它使用redis-cli程序完成。 要開始重新分片,只需鍵入:
您只需要指定一個節(jié)點,redis-cli將自動找到其他節(jié)點。 當(dāng)前redis-cli僅能在管理員支持下重新分片,您不能僅僅說將5%的插槽從該節(jié)點移到另一個節(jié)點(當(dāng)然這實現(xiàn)起來很簡單)。 因此,它會以一個問題開始。 首先是您想做多少重分片:
我們可以嘗試重新分派1000個hash槽,如果該示例仍在運行且沒有sleep調(diào)用,則該hash槽應(yīng)已包含少量的key。 然后redis-cli需要知道重新分片的目標(biāo)是什么,也就是將接收hash槽的節(jié)點。 我將使用第一個主節(jié)點,即127.0.0.1:7000,但是我需要指定實例的節(jié)點ID。redis-cli已將其打印在列表中,但是如果需要的話,我也可以使用以下命令找到節(jié)點的ID:
所以我的目標(biāo)節(jié)點應(yīng)該是是 97a3a64667477371c4479320d683e4c8db5858b1。 現(xiàn)在,它會問你要從哪些節(jié)點獲取這些key。我只輸入all,以便從所有其他主節(jié)點獲取一些hash槽。 最終確認后,您會看到一條消息,表明redis-cli將要從一個節(jié)點移動到另一個節(jié)點,并且將從一側(cè)移動到另一側(cè)的每個實際的key都會打印出來。 在重新分片過程中,您應(yīng)該能夠看到示例程序運行不受影響。如果需要,您還可以在重新分片期間停止并重新啟動它多次。重新分片結(jié)束時,可以使用以下命令測試集群的運行狀況:
所有插槽都會被覆蓋到,但是這次127.0.0.1:7000的主節(jié)點將具有更多的hash插槽 一個更有趣的示例應(yīng)用程序我們之前編寫的示例程序不怎么好。它以一種簡單的方式寫入集群,甚至無需檢查寫入的內(nèi)容是否正確。從我們的角度來看,接收寫操作的集群可以始終在每個操作里將名為foo的key寫到42這個hash槽里,而我們根本不會注意到。因此,在redis-rb-cluster代碼倉庫中,有一個更有趣的程序,稱為consistency-test.rb。它使用一組計數(shù)器,默認為1000,并且發(fā)送INCR命令以增加計數(shù)器的值。但是,該應(yīng)用程序不僅可以寫數(shù)據(jù),還可以做兩件事:
這意味著該程序是一個簡單的一致性檢查程序,可以告訴您集群是否丟失了一些寫操作,或者它是否接受了我們未收到確認的寫操作。在第一種情況下,我們將看到一個計數(shù)器的值小于我們之前記住的值,而在第二種情況下,該值將更大。 運行一致性測試應(yīng)用程序每秒產(chǎn)生一行輸出:
該行顯示執(zhí)行的讀取和寫入的次數(shù),以及錯誤的數(shù)目(由于系統(tǒng)不可用,因此由于錯誤而無法接受查詢)。如果發(fā)現(xiàn)不一致,則將新行添加到輸出中。例如,如果我在程序運行時手動重置了計數(shù)器,就會發(fā)生這種情況:
當(dāng)我將計數(shù)器設(shè)置為0時,實際值為114,因此程序會報告114的寫丟失了(集群無法記住的INCR命令)。該程序作為測試用例更加有趣,因此我們將使用它來測試Redis 集群故障轉(zhuǎn)移。 測試故障轉(zhuǎn)移注意:在此測試過程中,你應(yīng)打開一個tab標(biāo)簽頁并在上面運行一致性測試應(yīng)用程序。 為了觸發(fā)故障轉(zhuǎn)移,我們可以做的最簡單的事情(也就是在分布式系統(tǒng)中可能發(fā)生的語義上最簡單的失?。┦鞘箚蝹€進程崩潰,在我們的例子中是單個主機崩潰。 我們可以使用以下命令來識別主節(jié)點并使其崩潰:
好了,現(xiàn)在7000,7001,7002都是主節(jié)點,我們把7002這臺機器用DEBUG SEGFAULT命令使其崩潰。
現(xiàn)在我們可以看看這個一致性測試的輸出的報告是什么。
如您所見,在故障轉(zhuǎn)移期間,系統(tǒng)無法接受578次讀取和577次寫入,但是在數(shù)據(jù)庫中并未創(chuàng)建任何不一致的數(shù)據(jù)。 這聽起來可能是個意外,因為在本教程的第一部分中,我們說過Redis集群在故障轉(zhuǎn)移期間會丟失寫操作,因為它使用異步復(fù)制。我們沒有說的是,這其實不太可能發(fā)生,因為Redis會給客戶端發(fā)送回應(yīng),并且同樣的命令幾乎同時會復(fù)制到備份節(jié)點,因此丟失數(shù)據(jù)的窗口很小。但是,很難觸發(fā)這一事實并不意味著它不可能,因此這不會改變Redis集群提供的一致性保證。 現(xiàn)在,我們可以檢查故障轉(zhuǎn)移之后的集群設(shè)置是什么(請注意,我重新啟動了崩潰的實例,以便它作為備份節(jié)點重新加入集群):
現(xiàn)在,主節(jié)點在端口7000、7001和7005上運行。以前是主節(jié)點(在端口7002上運行的Redis實例)現(xiàn)在變成了7005的備份節(jié)點。 CLUSTER NODES命令的輸出可能看起來很復(fù)雜,但實際上非常簡單,由以下標(biāo)記組成:
手動故障轉(zhuǎn)移有時,強制進行故障轉(zhuǎn)移而實際上不會對主節(jié)點引起任何問題是很有用的。例如,為了升級主節(jié)點之一的Redis進程,最好對其進行故障轉(zhuǎn)移,以將其轉(zhuǎn)變?yōu)閷捎眯缘挠绊懽钚〉膫浞莨?jié)點。 Redis集群使用CLUSTER FAILOVER 命令支持手動故障轉(zhuǎn)移,該手動故障轉(zhuǎn)移必須在要進行故障轉(zhuǎn)移的主節(jié)點的備份節(jié)點之一中執(zhí)行。 與實際的主服務(wù)器故障導(dǎo)致的故障轉(zhuǎn)移相比,手動故障轉(zhuǎn)移是不一樣的,但它更安全,因為它們觸發(fā)的方式避免了此過程中的數(shù)據(jù)丟失,只有在系統(tǒng)確定新的主節(jié)點已經(jīng)在運行并且替代了舊的主節(jié)點的數(shù)據(jù)復(fù)制功能后,才能將客戶端從原來的主節(jié)點切換到新的主節(jié)點。 在執(zhí)行手動故障轉(zhuǎn)移時在備份節(jié)點日志中可以看到:
基本上,連接到我們將要進行故障轉(zhuǎn)移的主節(jié)點的客戶端都已停止。同時,主節(jié)點將其復(fù)制偏移發(fā)送到備份節(jié)點,備份節(jié)點會在它這邊等待偏移接收完畢。 當(dāng)復(fù)制偏移量完成時,故障轉(zhuǎn)移開始,并且將向舊的主節(jié)點通知配置切換。 當(dāng)客戶端在舊的主節(jié)點上解鎖時,它們將被重定向到新的主節(jié)點。 添加新節(jié)點添加新節(jié)點的基本過程是先添加一個空節(jié)點,然后將一些數(shù)據(jù)移入該節(jié)點(如果它是新的主節(jié)點),或者告訴它設(shè)置為已知節(jié)點的副本(如果它是備份節(jié)點)。從添加新的主節(jié)點開始,我們兩者都會展示。在這兩種情況下,要執(zhí)行的第一步都是添加一個空節(jié)點。這就像在端口7006中啟動一個新節(jié)點(現(xiàn)有的6個節(jié)點已經(jīng)從7000到7005使用新節(jié)點)一樣簡單,除了端口號之外,其他節(jié)點都使用相同的配置,因此您應(yīng)該按順序進行操作以符合我們之前節(jié)點使用的設(shè)置:
此時這個服務(wù)應(yīng)該運行起來了?,F(xiàn)在我們可以使用redis-cli來向已有的集群添加一個節(jié)點。
如您所見,我使用add-node命令將新節(jié)點的地址指定為第一個參數(shù),并將集群中隨機存在的節(jié)點的地址指定為第二個參數(shù)。實際上,redis-cli在這里對我們沒什么用,它只是向節(jié)點發(fā)送了CLUSTERMEET消息,這也可以手動完成。不過redis-cli會在運行之前檢查集群的狀態(tài),因此,即使您知道內(nèi)部結(jié)構(gòu)如何運行,通過redis-cli執(zhí)行集群操作是仍然是一個好主意。 現(xiàn)在,我們可以連接到新節(jié)點,以查看它是否確實加入了集群:
請注意,由于此節(jié)點已經(jīng)連接到集群,因此它已經(jīng)能夠正確重定向客戶端查詢,通常來說它已經(jīng)是集群的一部分了。 但是,與其他主節(jié)點相比,它有兩個特點:
現(xiàn)在可以使用redis-cli的重新分片功能將hash槽分配給該節(jié)點。像上一節(jié)中已經(jīng)展示的那樣,這里我就不展示了,他們的操作沒有區(qū)別,只是將空節(jié)點作為目標(biāo)進行重新分片。 添加一個節(jié)點作為副本(備份節(jié)點)添加一個備份節(jié)點可以通過2種方式完成。最常用的是用 redis-cli, 不過要用
請注意,此處的命令行與我們用于添加新主節(jié)點的命令行完全相同,因此我們并未指定要向其添加副本的主節(jié)點。在這種情況下,redis-cli要做的就是將新節(jié)點添加給副本較少的主節(jié)點中的隨機主節(jié)點的副本。但是,您可以使用以下命令行指定想要與新副本一起使用的主節(jié)點:
這樣我們便將新副本分配給特定的主節(jié)點。 將副本添加到特定主節(jié)點的一種更手動的方法是將新節(jié)點添加為空的主節(jié)點,然后使用CLUSTER REPLICATE命令將其轉(zhuǎn)換為副本。 如果將該節(jié)點添加為備份節(jié)點,但您想將其作為其他主節(jié)點的副本進行移動,也一樣適用。 例如,為了給節(jié)點127.0.0.1:7005添加副本,此節(jié)點當(dāng)前服務(wù)的hash槽正在11423-16383范圍內(nèi),節(jié)點ID為3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e,我要做的就是連接到新節(jié)點(已經(jīng)作為空的主節(jié)點添加到集群)并在新節(jié)點上發(fā)送命令:
就是這樣。 現(xiàn)在,這組hash槽有了一個新副本,并且集群中的所有其他節(jié)點都已經(jīng)知道(幾秒鐘后需要更新其配置)。 我們可以使用以下命令進行驗證:
節(jié)點3c3a0c...現(xiàn)在有了2個備份節(jié)點,運行在7002端口(已存在)和7006端口(新加入的) 移除節(jié)點為了移除一個備份節(jié)點,只需要在redis-cli上使用del-node 命令:
第一個參數(shù)只是集群中的一個隨機節(jié)點,第二個參數(shù)是您要刪除的節(jié)點的ID。您也可以用相同的方法刪除主節(jié)點,但是要刪除主節(jié)點,它必須為空。如果主節(jié)點不為空,則需要先將數(shù)據(jù)重新分片到所有其他主節(jié)點。 刪除主節(jié)點的另一種方法是在其一個備份節(jié)點上對其執(zhí)行手動故障轉(zhuǎn)移,并在該節(jié)點成為新主節(jié)點的備份節(jié)點之后刪除該節(jié)點。顯然,這在您想要減少集群中的主節(jié)點的實際數(shù)量時沒什么用,在這種情況下,需要重新分片。 副本遷移在Redis集群里里任何時間你都可以重新配置一個備份節(jié)點使其作為另一個主節(jié)點的從屬節(jié)點,使用下列命令:
但是,有一種特殊情況,您希望副本在沒有系統(tǒng)管理員幫助的情況下自動從一個主節(jié)點移動到另一個主節(jié)點。副本的自動重新配置稱為副本遷移,它能夠提高Redis集群的可靠性。 注意:您可以在Redis集群規(guī)范中閱讀副本遷移的詳細信息,這里我們僅提供一些一般的想法以及您應(yīng)該從中受益的信息。 在某些情況下,您可能想讓您的集群副本從一個主節(jié)點移動到另一個主節(jié)點的原因是,Redis集群通常具有與給定主節(jié)點的副本數(shù)量相同的故障容忍性。 例如,如果一個主節(jié)點及其副本同時失敗,則每個主節(jié)點都有一個副本的集群將無法繼續(xù)工作,這僅僅是因為沒有其他實例擁有與該主節(jié)點服務(wù)的相同的hash槽的副本。但是,盡管網(wǎng)絡(luò)斷裂可能會同時隔離多個節(jié)點,但是許多其他類型的故障(例如單個節(jié)點本地的硬件或軟件故障)是非常值得注意的一類故障,這類故障不太可能同時發(fā)生,因此在每個主節(jié)點都有一個備份節(jié)點的集群中,如果該備份節(jié)點在凌晨4點被關(guān)閉,而主節(jié)點在凌晨6點被關(guān)閉。這仍然會導(dǎo)致集群無法運行。 為了提高系統(tǒng)的可靠性,我們可以選擇向每個主節(jié)點添加副本,但這成本很高。副本遷移允許將更多備份節(jié)點添加到少數(shù)幾個主節(jié)點中。因此,您有10個節(jié)點,每個節(jié)點有1個備份節(jié)點,總共20個實例。但是,比如您增加了3個實例作為某些主節(jié)點的備份節(jié)點,因此某些主節(jié)點將具有多個副本了。 使用副本遷移時,如果一個主節(jié)點不包含備份節(jié)點,則具有多個備份節(jié)點的主節(jié)點的副本將遷移到孤立的主節(jié)點。因此,當(dāng)您的備份節(jié)點在上述示例中的凌晨4點關(guān)閉之后,另一個備份節(jié)點將接替它;當(dāng)主節(jié)點在凌晨5點也發(fā)生故障時,另一個備份節(jié)點將被選舉成為主節(jié)點,以便集群可以繼續(xù)操作。 所以您應(yīng)該了解哪些有關(guān)副本遷移的知識?
|
|