在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ 大數(shù)據(jù)/ 集群(上)
使用 Redis 實(shí)現(xiàn) Twitter(上)
集群(下)
使用 Redis 實(shí)現(xiàn) Twitter(下)
使用 Redis 作為 LRU 緩存
高可用(上)
高可用客戶端指引
集群(中)
高可用(下)
持久化
Redis 介紹
集中插入
集群(上)
從入門到精通(上)
從入門到精通(下)
從入門到精通(中)
分片
數(shù)據(jù)類型初探
復(fù)制

集群(上)

這篇文檔是對(duì) Redis 集群的介紹,沒(méi)有使用復(fù)雜難懂的東西來(lái)理解分布式系統(tǒng)的概念。本文提供了如何建立,測(cè)試和操作一個(gè)集群的相關(guān)指導(dǎo),但沒(méi)有涉及在 Redis 集群規(guī)范(參考本系列其他文章,譯者注)中的諸多細(xì)節(jié),只是從用戶的視角來(lái)描述系統(tǒng)是如何運(yùn)作的。

注意,如果你打算來(lái)一次認(rèn)真的 Redis 集群的部署,更正式的規(guī)范文檔(關(guān)注本系列文章,譯者注)強(qiáng)烈建議你好好讀一讀。

Redis 集群當(dāng)前處于 alpha 階段,如果你發(fā)現(xiàn)任何問(wèn)題,請(qǐng)聯(lián)系 Redis 郵件列表,或者在 Redis 的 Github 倉(cāng)庫(kù)中開(kāi)啟一個(gè)問(wèn)題(issue)。

Redis 集群(Redis Cluster)

Redis 集群提供一種運(yùn)行 Redis 的方式,數(shù)據(jù)被自動(dòng)的分片到多個(gè) Redis 節(jié)點(diǎn)。

集群不支持處理多個(gè)鍵的命令,因?yàn)檫@需要在 Redis 節(jié)點(diǎn)間移動(dòng)數(shù)據(jù),使得 Redis 集群不能提供像 Redis 單點(diǎn)那樣的性能,在高負(fù)載下會(huì)表現(xiàn)得不可預(yù)知。

Redis 集群也提供在網(wǎng)絡(luò)分割(partitions)期間的一定程度的可用性,這就是在現(xiàn)實(shí)中當(dāng)一些節(jié)點(diǎn)失敗或者不能通信時(shí)能繼續(xù)進(jìn)行運(yùn)轉(zhuǎn)的能力。

所以,在實(shí)踐中,你可以從 Redis 集群中得到什么呢?

  • 在多個(gè)節(jié)點(diǎn)間自動(dòng)拆分你的數(shù)據(jù)集的能力。
  • 當(dāng)部分節(jié)點(diǎn)正在經(jīng)歷失敗或者不能與集群其他節(jié)點(diǎn)通信時(shí)繼續(xù)運(yùn)轉(zhuǎn)的能力。

Redis 集群的 TCP 端口(Redis Cluster TCP ports)

每個(gè) Redis 集群節(jié)點(diǎn)需要兩個(gè) TCP 連接打開(kāi)。正常的 TCP 端口用來(lái)服務(wù)客戶端,例如 6379,加 10000 的端口用作數(shù)據(jù)端口,在上面的例子中就是 16379。

第二個(gè)大一些的端口用于集群總線(bus),也就是使用二進(jìn)制協(xié)議的點(diǎn)到點(diǎn)通信通道。集群總線被節(jié)點(diǎn)用于錯(cuò)誤檢測(cè),配置更新,故障轉(zhuǎn)移授權(quán)等等。客戶端不應(yīng)該嘗試連接集群總線端口,而應(yīng)一直與正常的 Redis 命令端口通信,但是要確保在防火墻中打開(kāi)了這兩個(gè)端口,否則 Redis 集群的節(jié)點(diǎn)不能相互通信。

命令端口和集群總線端口的偏移量一直固定為 10000。

注意,為了讓 Redis 集群工作正常,對(duì)每個(gè)節(jié)點(diǎn):

  1. 用于與客戶端通信的正常的客戶端通信端口(通常為 6379)需要開(kāi)放給所有需要連接集群的客戶端以及其他集群節(jié)點(diǎn)(使用客戶端端口來(lái)進(jìn)行鍵遷移)。
  2. 集群總線端口(客戶端端口加 10000)必須從所有的其他集群節(jié)點(diǎn)可達(dá)。

如果你不打開(kāi)這兩個(gè) TCP 端口,你的集群就不會(huì)像你期待的那樣去工作。

Redis 集群的數(shù)據(jù)分片(Redis Cluster data sharding)

Redis 集群沒(méi)有使用一致性哈希,而是另外一種不同的分片形式,每個(gè)鍵概念上是被我們稱為哈希槽(hash slot)的東西的一部分。

Redis 集群有 16384 個(gè)哈希槽,我們只是使用鍵的 CRC16 編碼對(duì) 16384 取模來(lái)計(jì)算一個(gè)指定鍵所屬的哈希槽。

每一個(gè) Redis 集群中的節(jié)點(diǎn)都承擔(dān)一個(gè)哈希槽的子集,例如,你可能有一個(gè) 3 個(gè)節(jié)點(diǎn)的集群,其中:

  • 節(jié)點(diǎn) A 包含從 0 到 5500 的哈希槽。
  • 節(jié)點(diǎn) B 包含從 5501 到 11000 的哈希槽。
  • 節(jié)點(diǎn) C 包含從 11001 到 16384 的哈希槽。

這可以讓在集群中添加和移除節(jié)點(diǎn)非常容易。例如,如果我想添加一個(gè)新節(jié)點(diǎn) D,我需要從節(jié)點(diǎn) A,B,C 移動(dòng)一些哈希槽到節(jié)點(diǎn) D。同樣地,如果我想從集群中移除節(jié)點(diǎn) A,我只需要移動(dòng) A 的哈希槽到 B 和 C。當(dāng)節(jié)點(diǎn) A 變成空的以后,我就可以從集群中徹底刪除它。

因?yàn)閺囊粋€(gè)節(jié)點(diǎn)向另一個(gè)節(jié)點(diǎn)移動(dòng)哈希槽并不需要停止操作,所以添加和移除節(jié)點(diǎn),或者改變節(jié)點(diǎn)持有的哈希槽百分比,都不需要任何停機(jī)時(shí)間(downtime)。

Redis 集群的主從模型(Redis Cluster master-slave model)

為了當(dāng)部分節(jié)點(diǎn)失效時(shí),或者無(wú)法與大多數(shù)節(jié)點(diǎn)通信時(shí)仍能保持可用,Redis 集群采用每個(gè)節(jié)點(diǎn)擁有 1(主服務(wù)自身)到 N 個(gè)副本(N-1 個(gè)附加的從服務(wù)器)的主從模型。

在我們的例子中,集群擁有 A,B,C 三個(gè)節(jié)點(diǎn),如果節(jié)點(diǎn) B 失效集群將不能繼續(xù)服務(wù),因?yàn)槲覀儾辉儆修k法來(lái)服務(wù)在 5501-11000 范圍內(nèi)的哈希槽。

但是,如果當(dāng)我們創(chuàng)建集群后(或者稍后),我們?yōu)槊恳粋€(gè)主服務(wù)器添加一個(gè)從服務(wù)器,這樣最終的集群就由主服務(wù)器 A,B,C 和從服務(wù)器 A1,B1,C1 組成,如果 B 節(jié)點(diǎn)失效系統(tǒng)仍能繼續(xù)服務(wù)。

B1 節(jié)點(diǎn)復(fù)制 B 節(jié)點(diǎn),于是集群會(huì)選舉 B1 節(jié)點(diǎn)作為新的主服務(wù)器,并繼續(xù)正確的運(yùn)轉(zhuǎn)。

Redis 集群的一致性保證(Redis Cluster consistency guarantees)

Redis 集群不保證強(qiáng)一致性。實(shí)踐中,這意味著在特定的條件下,Redis 集群可能會(huì)丟掉一些被系統(tǒng)收到的寫入請(qǐng)求命令。

Redis 集群為什么會(huì)丟失寫請(qǐng)求的第一個(gè)原因,是因?yàn)椴捎昧水惒綇?fù)制。這意味著在寫期間下面的事情發(fā)生了:

  • 你的客戶端向主服務(wù)器 B 寫入。
  • 主服務(wù)器 B 回復(fù) OK 給你的客戶端。
  • 主服務(wù)器 B 傳播寫入操作到其從服務(wù)器 B1,B2 和 B3。

你可以看到,B 在回復(fù)客戶端之前沒(méi)有等待從 B1,B2,B3 的確認(rèn),因?yàn)檫@是一個(gè)過(guò)高的延遲代價(jià),所以如果你的客戶端寫入什么東西,B 確認(rèn)了這個(gè)寫操作,但是在發(fā)送寫操作到其從服務(wù)器前崩潰了,其中一個(gè)從服務(wù)器被提升為主服務(wù)器,永久性的丟失了這個(gè)寫操作。

這非常類似于在大多數(shù)被配置為每秒刷新數(shù)據(jù)到磁盤的數(shù)據(jù)庫(kù)發(fā)生的事情一樣,這是一個(gè)可以根據(jù)以往不包括分布式系統(tǒng)的傳統(tǒng)數(shù)據(jù)庫(kù)系統(tǒng)的經(jīng)驗(yàn)來(lái)推理的場(chǎng)景。同樣的,你可以通過(guò)在回復(fù)客戶端之前強(qiáng)制數(shù)據(jù)庫(kù)刷新數(shù)據(jù)到磁盤來(lái)改進(jìn)一致性,但這通常會(huì)極大的降低性能。

基本上,有一個(gè)性能和一致性之間的權(quán)衡。

注意:未來(lái),Redis 集群在必要時(shí)可能或允許用戶執(zhí)行同步寫操作。

Redis 集群丟失寫操作還有另一個(gè)場(chǎng)景,發(fā)生在網(wǎng)絡(luò)分割時(shí),客戶端與至少包含一個(gè)主服務(wù)器的少數(shù)實(shí)例被孤立起來(lái)了。

舉個(gè)例子,我們的集群由 A,B,C,A1,B1,C1 共 6 個(gè)節(jié)點(diǎn)組成,3 個(gè)主服務(wù)器,3 個(gè)從服務(wù)器。還有一個(gè)客戶端,我們稱為 Z1。

分割發(fā)生以后,有可能分割的一側(cè)是 A,C,A1,B1,C1,分割的另一側(cè)是 B 和 Z1。

Z1 仍然可以寫入到可接受寫請(qǐng)求的 B。如果分割在很短的時(shí)間內(nèi)恢復(fù),集群會(huì)正常的繼續(xù)。但是,如果分割持續(xù)了足夠的時(shí)間,B1 在分割的大多數(shù)這一側(cè)被提升為主服務(wù)器,Z1 發(fā)送給 B 的寫請(qǐng)求會(huì)丟失。

注意,Z1 發(fā)送給 B 的寫操作數(shù)量有一個(gè)最大窗口:如果分割的大多數(shù)側(cè)選舉一個(gè)從服務(wù)器為主服務(wù)器后過(guò)了足夠多的時(shí)間,少數(shù)側(cè)的每一個(gè)主服務(wù)器節(jié)點(diǎn)將停止接受寫請(qǐng)求。

這個(gè)時(shí)間量是 Redis 集群一個(gè)非常重要的配置指令,稱為節(jié)點(diǎn)超時(shí)(node timeout)。

節(jié)點(diǎn)超時(shí)時(shí)間過(guò)后,主服務(wù)器節(jié)點(diǎn)被認(rèn)為失效,可以用其一個(gè)副本來(lái)取代。同樣地,節(jié)點(diǎn)超時(shí)時(shí)間過(guò)后,主服務(wù)器節(jié)點(diǎn)還不能感知其它主服務(wù)器節(jié)點(diǎn)的大多數(shù),則進(jìn)入錯(cuò)誤狀態(tài),并停止接受寫請(qǐng)求。

創(chuàng)建和使用 Redis 集群(Creating and using a Redis Cluster)

要?jiǎng)?chuàng)建一個(gè)集群,我們要做的第一件事情就是要有若干運(yùn)行在集群模式下的 Redis 實(shí)例。這基本上意味著,集群不是使用正常的 Redis 實(shí)例創(chuàng)建的,而是需要配置一種特殊的模式 Redis 實(shí)例才會(huì)開(kāi)啟集群特定的特性和命令。

下面是最小的 Redis 集群配置文件:

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

正如你所看到的,簡(jiǎn)單的 cluster-enabled 指令開(kāi)啟了集群模式。每個(gè)實(shí)例包含一個(gè)保存這個(gè)節(jié)點(diǎn)配置的文件的路徑,默認(rèn)是 nodes.conf。這個(gè)文件不會(huì)被用戶接觸到,啟動(dòng)時(shí)由 Redis 集群實(shí)例生成,每次在需要時(shí)被更新。

注意,可以正常運(yùn)轉(zhuǎn)的最小集群需要包含至少 3 個(gè)主服務(wù)器節(jié)點(diǎn)。在你的第一次嘗試中,強(qiáng)烈建議開(kāi)始一個(gè) 6 個(gè)節(jié)點(diǎn)的集群,3 個(gè)主服務(wù)器,3 個(gè)從服務(wù)器。

要這么做,先進(jìn)入一個(gè)新的目錄,創(chuàng)建下面這些以端口號(hào)來(lái)命名的目錄,我們后面會(huì)在每個(gè)目錄中運(yùn)行實(shí)例。

像這樣:

mkdir cluster-test  
cd cluster-test  
mkdir 7000 7001 7002 7003 7004 7005  

在從 7000 到 7005 的每個(gè)目錄內(nèi)創(chuàng)建一個(gè) redis.conf 文件。作為你的配置文件的模板,只使用上面的小例子,但是要確保根據(jù)目錄名來(lái)使用正確的端口號(hào)來(lái)替換端口號(hào) 7000。

現(xiàn)在,復(fù)制你從 Github 的不穩(wěn)定分支的最新的源代碼編譯出來(lái)的 redis-server 可執(zhí)行文件到 cluster-test 目錄中,最后在你喜愛(ài)的終端應(yīng)用程序中打開(kāi) 6 個(gè)終端標(biāo)簽。

像這樣在每個(gè)標(biāo)簽中啟動(dòng)實(shí)例:

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

你可以從每個(gè)實(shí)例的日志中看到,因?yàn)?nodes.conf 文件不存在,每個(gè)節(jié)點(diǎn)都為自己賦予了一個(gè)新 ID。

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

這個(gè) ID 會(huì)一直被這個(gè)實(shí)例使用,這樣實(shí)例就有一個(gè)在集群上下文中唯一的名字。每個(gè)節(jié)點(diǎn)使用這個(gè) ID 來(lái)記錄每個(gè)其它節(jié)點(diǎn),而不是靠 IP 和端口。IP 地址和端口可能會(huì)變化,但是唯一的節(jié)點(diǎn)標(biāo)識(shí)符在節(jié)點(diǎn)的整個(gè)生命周期中都不會(huì)改變。我們稱這個(gè)標(biāo)識(shí)符為節(jié)點(diǎn) ID(Node ID)。

創(chuàng)建集群(Creating the cluster)

現(xiàn)在,我們已經(jīng)有了一些運(yùn)行中的實(shí)例,我們需要?jiǎng)?chuàng)建我們的集群,寫一些有意義的配置到節(jié)點(diǎn)中。

這很容易完成,因?yàn)槲覀冇蟹Q為 redis-trib 的 Redis 集群命令行工具來(lái)幫忙,這是一個(gè) Ruby 程序,可以在實(shí)例上執(zhí)行特殊的命令來(lái)創(chuàng)建一個(gè)新的集群,檢查或重分片一個(gè)已存在的集群,等等。

redis-trib 工具在 Redis 源代碼分發(fā)版本的 src 目錄中。要?jiǎng)?chuàng)建你的集群,簡(jiǎn)單輸入:

./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,因?yàn)槲覀兿雱?chuàng)建一個(gè)新的集群。--replicas 1 選項(xiàng)意思是我們希望每個(gè)創(chuàng)建的主服務(wù)器有一個(gè)從服務(wù)器。其他參數(shù)是我想用來(lái)創(chuàng)建新集群的實(shí)例地址列表。

顯然,我們要求的唯一布局就是創(chuàng)建一個(gè)擁有 3 個(gè)主服務(wù)器和 3 個(gè)從服務(wù)器的集群。

Redis-trib 會(huì)建議你一個(gè)配置。輸入 yes 接受。集群會(huì)被配置和連接在一起,也就是說(shuō),實(shí)例會(huì)被引導(dǎo)為互相之間對(duì)話。最后,如果一切順利你會(huì)看到一個(gè)類似這樣的消息:

[OK] All 16384 slots covered  

這表示,16384 個(gè)槽中的每一個(gè)至少有一個(gè)主服務(wù)器在處理。

與集群共舞(Playing with the cluste)

在當(dāng)前階段,Redis 集群的一個(gè)問(wèn)題是缺少客戶端庫(kù)的實(shí)現(xiàn)。

據(jù)我所知有以下實(shí)現(xiàn):

  • redis-rb-cluster 是我(@antirez)寫的 Ruby 實(shí)現(xiàn),作為其他語(yǔ)言的參考。這個(gè)是對(duì)原先的
  • redis-rb 進(jìn)行了簡(jiǎn)單的封裝,實(shí)現(xiàn)了與集群高效對(duì)話的最小語(yǔ)義。
  • redis-py-cluster 看起來(lái)就是 redis-rb-cluster 的 Python 版本。最新沒(méi)有更新(最后一次提交是 6 個(gè)月之前)但是這是一個(gè)起點(diǎn)。
  • 流行的 Predis 有對(duì) Redis 集群的支持,支持最近有更新,并處于活躍開(kāi)發(fā)狀態(tài)。
  • 最多使用的 Java 客戶端 Jedis 最近增加了對(duì) Redis 集群的支持,請(qǐng)查看項(xiàng)目 README 中的 Jedis 集群部分。
  • StackExchange.Redis 提供對(duì) C#的支持(應(yīng)該與大多數(shù).NET 語(yǔ)言工作正常:VB,F(xiàn)#等)。
  • Github 上 Redis 倉(cāng)庫(kù)的不穩(wěn)定分支上的 redis-cli 工具實(shí)現(xiàn)了一個(gè)基本的集群支持,使用-c 啟動(dòng)時(shí)切換。

測(cè)試 Redis 集群的簡(jiǎn)單辦法就是嘗試上面這些客戶端,或者只是使用 redis-cli 命令行工具。下面的交互例子使用的是后者:

$ redis-cli -c -p 7000  
redis 127.0.0.1:7000> set foo bar  
-> Redirected to slot [12182] located at 127.0.0.1:7002  
OK  
redis 127.0.0.1:7002> set hello world  
-> Redirected to slot [866] located at 127.0.0.1:7000  
OK  
redis 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-cli 的集群支持非?;?,所以總是依賴 Redis 集群節(jié)點(diǎn)重定向客戶端到正確的節(jié)點(diǎn)。一個(gè)真正的客戶端可以做得更好,緩存哈希槽和節(jié)點(diǎn)地址之間的映射,直接使用到正確節(jié)點(diǎn)的正確連接。映射只在集群的配置發(fā)生某些變化時(shí)才重新刷新,例如,故障轉(zhuǎn)移以后,或者系統(tǒng)管理員通過(guò)添加或移除節(jié)點(diǎn)改變了集群的布局以后。

上一篇:集中插入下一篇:復(fù)制