




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、原文地址:h/topic/cluster-tutorial.html本文檔翻譯自。本文檔是 Redis群的方法。集群的入門, 從用戶的角度介紹了設(shè)置、測試和操作集本Redis那么不包含晦澀難懂的分布式概念, 也沒有像 Redis 集群規(guī)范 那樣包含集群的實(shí)現(xiàn)細(xì)節(jié), 如果你打算深入地學(xué)習(xí) Redis 集群的部署方法,你在閱讀完這個(gè)之后, 再去看一看集群規(guī)范。Redis 集群目前仍處于 Alpha 測試版本, 如果在使用過程中發(fā)現(xiàn)任何問題,請到 Redis 的郵件列表 發(fā)貼, 或者到 Redis 的頁面錯(cuò)誤。集群簡介Redis 集群是一個(gè)可以在多個(gè) Redis 節(jié)點(diǎn)之間進(jìn)行數(shù)據(jù)共享的設(shè)施(inst
2、allation)。Redis 集群不支持那些需要同時(shí)處理多個(gè)鍵的 Redis 命令, 因?yàn)閳?zhí)行這些命令需要在多個(gè) Redis 節(jié)點(diǎn)之間移動(dòng)數(shù)據(jù), 并且在高負(fù)載的情況下, 這些命令將降低 Redis 集群的性能, 并導(dǎo)致不可的行為。Redis 集群通過分區(qū)(partition)來提供一定程度的可用性(availability):即使集群中有一部分節(jié)點(diǎn)失效或者無法進(jìn)行通訊, 集群也可以繼續(xù)處理命令請求。Redis 集群提供了以下兩個(gè)好處:將數(shù)據(jù)自動(dòng)切分(split)到多個(gè)節(jié)點(diǎn)的能力。當(dāng)集群中的一部分節(jié)點(diǎn)失效或者無法進(jìn)行通訊時(shí), 仍然可以繼續(xù)處理命令請求的能力。集群因?yàn)閷⒁粋€(gè)哈希槽從一個(gè)節(jié)點(diǎn)移動(dòng)到
3、另一個(gè)節(jié)點(diǎn)不會(huì)造成節(jié)點(diǎn)阻塞, 所以無論是添加新節(jié)點(diǎn)還是移除已存在節(jié)點(diǎn), 又或者改變某個(gè)節(jié)點(diǎn)包含的哈希槽數(shù)量,都不會(huì)造成集群下線。Redis 集群中的主從為了使得集群在一部分節(jié)點(diǎn)下線或者無法與集群的大多數(shù)(majority)節(jié)點(diǎn)進(jìn)行通訊的情況下, 仍然可以正常, Redis 集群對節(jié)點(diǎn)使用了主從功 能: 集群中的每個(gè)節(jié)點(diǎn)都有 1 個(gè)至 N 個(gè) 品(replica), 其中一個(gè)品為主節(jié)點(diǎn)(master), 而其余的 N-1 個(gè)品為從節(jié)點(diǎn)(slave)。在之前列舉的節(jié)點(diǎn) A 、B 、C 的例子中, 如果節(jié)點(diǎn) B 下線了, 那么集群將無法正常運(yùn)行, 因?yàn)榧赫也坏焦?jié)點(diǎn)來處理 5501 號至 11000
4、 號的哈希槽。如果用戶將新節(jié)點(diǎn) D 添加到集群中, 那么集群只需要將節(jié)點(diǎn) A 、B 、 C 中的某些槽移動(dòng)到節(jié)點(diǎn) D 就可以了。與此類似, 如果用戶要從集群中移除節(jié)點(diǎn) A , 那么集群只需要將節(jié)點(diǎn) A 中的所有哈希槽移動(dòng)到節(jié)點(diǎn) B 和節(jié)點(diǎn) C , 然后再移除空白(不包含任何哈希槽)的節(jié)點(diǎn) A 就可以了。這種將哈希槽分布到不同節(jié)點(diǎn)的做法使得用戶可以很容易地向集群中添加或者刪除節(jié)點(diǎn)。 比如說:節(jié)點(diǎn) A 負(fù)責(zé)處理 0 號至 5500 號哈希槽。節(jié)點(diǎn) B 負(fù)責(zé)處理 5501 號至 11000 號哈希槽。節(jié)點(diǎn) C 負(fù)責(zé)處理 11001 號至 16384 號哈希槽。Redis 集群數(shù)據(jù)共享Redis 集群
5、使用數(shù)據(jù)分片(sharding)而非一致性哈希(consistency hashing)來實(shí)現(xiàn): 一個(gè) Redis 集群包含 16384 個(gè)哈希槽(hash slot), 數(shù)據(jù)庫中的每個(gè)鍵都屬于這 16384 個(gè)哈希槽的其中一個(gè), 集群使用公式 CRC16(key)%16384 來計(jì)算鍵 key 屬于哪個(gè)槽, 其中 CRC16(key) 語句用于計(jì)算鍵 key 的 CRC16 校驗(yàn)和 。集群中的每個(gè)節(jié)點(diǎn)負(fù)責(zé)處理一部分哈希槽。 舉個(gè)例子, 一個(gè)集群可以有三個(gè)哈希槽, 其中:如你所見, 主節(jié)點(diǎn)對命令的工作發(fā)生在返回命令回復(fù)之后, 因?yàn)槿绻?次處理命令請求都需要等待操作完成的話, 那么主節(jié)點(diǎn)處理命
6、令請求的速度將極大地降低 須在性能和一致性之間做出權(quán)衡。如果真的有必要的話, Redis 集群可能會(huì)在將來提供同步地(synchronou)執(zhí)行寫命令的方法。Redis 集群另外一種可能會(huì)丟失命令的情況是, 集群出現(xiàn)網(wǎng)絡(luò)(network partition), 并且一個(gè)客戶端與至少包括一個(gè)主節(jié)點(diǎn)在內(nèi)的少數(shù)(minority)實(shí)例被孤立。舉個(gè)例子, 假設(shè)集群包含 A 、 B 、 C 、 A1 、 B1 、 C1 六個(gè)節(jié)點(diǎn),其中 A 、B 、C 為主節(jié)點(diǎn), 而 A1 、B1 、C1 分別為三個(gè)主節(jié)點(diǎn)的從節(jié)點(diǎn), 另外還有一個(gè)客戶端 Z1 。假設(shè)集群中發(fā)生網(wǎng)絡(luò), 那么集群可能會(huì)為兩方, 大多數(shù)(maj
7、ority)的一方包含節(jié)點(diǎn) A 、C 、A1 、B1 和 C1 , 而少數(shù)(minority)的一方則包含節(jié)點(diǎn) B 和客戶端 Z1 ??蛻舳讼蛑鞴?jié)點(diǎn) B 發(fā)送一條寫命令。主節(jié)點(diǎn) B 執(zhí)行寫命令,并向客戶端返回命令回復(fù)。主節(jié)點(diǎn) B 將剛剛執(zhí)行的寫命令給它的從節(jié)點(diǎn) B1 、 B2 和 B3 。另一方面, 假如在創(chuàng)建集群的時(shí)候(或者至少在節(jié)點(diǎn) B 下線之前),為主節(jié)點(diǎn) B 添加了從節(jié)點(diǎn) B1 , 那么當(dāng)主節(jié)點(diǎn) B 下線的時(shí)候, 集群就會(huì)將B1 設(shè)置為新的主節(jié)點(diǎn), 并讓它代替下線的主節(jié)點(diǎn) B , 繼續(xù)處理 5501 號至 11000 號的哈希槽, 這樣集群就不會(huì)因?yàn)橹鞴?jié)點(diǎn) B 的下線而無法正常了。不過
8、如果節(jié)點(diǎn) B 和 B1 都下線的話, Redis 集群還是會(huì)停止。Redis 集群的一致性保證(guarantee)Redis 集群不保證數(shù)據(jù)的強(qiáng)一致性(strong consistency): 在特定條件下,Redis 集群可能會(huì)丟失已經(jīng)被執(zhí)行過的寫命令。使用異步(asynchronous replication)是 Redis 集群可能會(huì)丟失寫命令的其中一個(gè)原因。 考慮以下這個(gè)寫命令的例子:注意, 在網(wǎng)絡(luò)出現(xiàn)期間, 客戶端 Z1 可以向主節(jié)點(diǎn) B 發(fā)送寫命令的最 大時(shí)間是有限制的, 這一時(shí)間限制稱為節(jié)點(diǎn)超時(shí)時(shí)間(node timeout), 是 Redis 集群的一個(gè)重要的配置選項(xiàng):對于大
9、多數(shù)一方來說, 如果一個(gè)主節(jié)點(diǎn)未能在節(jié)點(diǎn)超時(shí)時(shí)間所設(shè)定的時(shí)限內(nèi)重新 聯(lián)系上集群, 那么集群會(huì)將這個(gè)主節(jié)點(diǎn)視為下線, 并使用從節(jié)點(diǎn)來代替這個(gè)主節(jié)port 7000cluster-enabled yescluster-config-file nodes.conf cluster-node-timeout 5000創(chuàng)建并使用 Redis 集群Redis 集群由多個(gè)運(yùn)行在集群模式(cluster mode)下的 Redis 實(shí)例組成, 實(shí)例的集群模式需要通過配置來開啟, 開啟集群模式的實(shí)例將可以使用集群特有的功能和命令。以下是一個(gè)包含了最少選項(xiàng)的集群配置文件示例:點(diǎn)繼續(xù)工作。對于少數(shù)一方, 如果一個(gè)主
10、節(jié)點(diǎn)未能在節(jié)點(diǎn)超時(shí)時(shí)間所設(shè)定的時(shí)限內(nèi)重新聯(lián)系上集群, 那么它將停止處理寫命令, 并向客戶端錯(cuò)誤。如果網(wǎng)絡(luò) 出現(xiàn)的時(shí)間很短, 那么集群會(huì)繼續(xù)正常運(yùn)行;但是, 如果網(wǎng)絡(luò) 出現(xiàn)的時(shí)間足夠長, 使得大多數(shù)一方將從節(jié)點(diǎn) B1 設(shè)置為新的主節(jié)點(diǎn), 并使用 B1 來代替原來的主節(jié)點(diǎn) B , 那么 Z1 發(fā)送給主節(jié)點(diǎn) B的寫命令將丟失。在網(wǎng)絡(luò)期間, 主節(jié)點(diǎn) B 仍然會(huì)接受 Z1 發(fā)送的寫命令:文件中的 cluster-enabled 選項(xiàng)用于開實(shí)例的集群模式, 而 cluster-conf-在文件夾 7000 至 7005 中, 各創(chuàng)建一個(gè) redis.conf 文件, 文件的內(nèi)容可以 使用上面的示例配置文件
11、, 但記得將配置中的端從 7000 改為與文件夾名 cd 7000./redis-server ./redis.conf字相同的號碼?,F(xiàn)在, 從 Redis頁面 的 unstable 分支中取出 的 Redis 源碼,編譯出可執(zhí)行文件 redis-server , 并將文件 到 cluster-test 文件夾,然后使用類似以下命令, 在每個(gè) 頁中打開一個(gè)實(shí)例:mkdir cluster-test cd cluster-testmkdir 7000 7001 7002 7003 7004 7005file 選項(xiàng)則設(shè)定了保存節(jié)點(diǎn)配置文件的路徑, 默認(rèn)值為 nodes.conf 。節(jié)點(diǎn)配置文件無須
12、人為修改, 它由 Redis 集群在啟動(dòng)時(shí)創(chuàng)建, 并在有需要時(shí)自動(dòng)進(jìn)行更新。要讓集群正常 至少需要三個(gè)主節(jié)點(diǎn), 不過在剛開始試用集群功能時(shí), 強(qiáng)烈建議使用六個(gè)節(jié)點(diǎn): 其中三個(gè)為主節(jié)點(diǎn), 而其余三個(gè)則是各個(gè)主節(jié)點(diǎn)的從節(jié)點(diǎn)。首先, 讓進(jìn)入一個(gè)新目錄, 并創(chuàng)建六個(gè)以端為名字的子目錄, 稍后在將每個(gè)目錄中運(yùn)行一個(gè) Redis 實(shí)例:appendonly yes127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005./redis-trib.rb create -replicas 1 127.0.0.1:7000
13、實(shí)例會(huì)一直使用同一個(gè) ID , 從而在集群中保持一個(gè)獨(dú)一無二(unique)的名字。每個(gè)節(jié)點(diǎn)都使用 ID 而不是 IP 或者端 來 其他節(jié)點(diǎn), 因?yàn)?IP 地址和端 都可能會(huì)改變, 而這個(gè)獨(dú)一無二的標(biāo)識符(identifier)則會(huì)在節(jié)點(diǎn)的整個(gè)生命周期中一直保持不變。這個(gè)標(biāo)識符稱為節(jié)點(diǎn) ID。創(chuàng)建集群現(xiàn)在已經(jīng)有了六個(gè)正在運(yùn)行中的 Redis 實(shí)例, 接下來需要使用這些實(shí)例來創(chuàng)建集群, 并為每個(gè)節(jié)點(diǎn)編寫配置文件。通過使用 Redis 集群命令行工具 redis-trib , 編寫節(jié)點(diǎn)配置文件的工作可以非常容易地完成: redis-trib 位于 Redis 源碼的 src 文件夾中, 它是一個(gè)
14、Ruby 程序, 這個(gè)程序通過向?qū)嵗l(fā)送特殊命令來完成創(chuàng)建新集群, 檢查集群, 或者對集群進(jìn)行重新分片(reshared)等工作。需要執(zhí)行以下命令來創(chuàng)建集群:Im 97a3a64667477371c4479320d683e4c8db5858b182462 26 Nov 11:56:55.329 * No cluster configuration found,實(shí)例打印的日志顯示, 因?yàn)?nodes.conf 文件不存在, 所以每個(gè)節(jié)點(diǎn)都為它自身指定了一個(gè)新的 ID : Creating clusterConnecting to node 127.0.0.1:7000: OK Connectin
15、g to node 127.0.0.1:7001: OK Connecting to node 127.0.0.1:7002: OK Connecting to node 127.0.0.1:7003: OK Connecting to node 127.0.0.1:7004: OK Connecting to node 127.0.0.1:7005: OK Performing hash slots allocation on 6 nodes.Using 3 masters:簡單來說, 以上命令的意思就是讓 redis-trib 程序創(chuàng)建一個(gè)包含三個(gè)主節(jié)點(diǎn)和三個(gè)從節(jié)點(diǎn)的集群。接著, redi
16、s-trib 會(huì)打印出一份預(yù)想中的配置給你看, 如果你覺得沒問題的話, 就可以輸入 yes , redis-trib 就會(huì)將這份配置應(yīng)用到集群當(dāng)中:給定 redis-trib.rb 程序令是 create , 這表示希望創(chuàng)建一個(gè)新的集群。選項(xiàng) -replicas 1 表示希望為集群中的每個(gè)主節(jié)點(diǎn)創(chuàng)建一個(gè)從節(jié)點(diǎn)。之后跟著的其他參數(shù)則是實(shí)例的地址列表,希望程序使用這些地址所指示的實(shí)例來創(chuàng)建新集群。命令的意義如下:127.0.0.1:7000127.0.0.1:7001127.0.0.1:7002127.0.0.1:7000replica#1is127.0.0.1:7003127.0.0.1:700
17、1replica#1is127.0.0.1:7004127.0.0.1:7002replica#1is127.0.0.1:7005M: 9991306f0e50640a5684f1958fd754b38fa034c9127.0.0.1:7000slots:0-5460 (5461 slots) masterM: e68e52cee0550f558b03b342f2f0354d2b8a083b127.0.0.1:7001slots:5461-10921 (5461 slots) masterM: 393c6df5eb4b4cec323f0e4ca961c8b256e3460a127.0.0.1:
18、7002slots:10922-16383 (5462 slots) masterS: 48b728dbcedff6bf056231eb44990b7d1c35c3e0127.0.0.1:7003S: 345ede084ac784a5c030a0387f8aaa9edfc59af3127.0.0.1:7004輸入 yes 并按下回車確認(rèn)之后, 集群就會(huì)將配置應(yīng)用到各個(gè)節(jié)點(diǎn), 并連接起 (join)各個(gè)節(jié)點(diǎn) 也即是, 讓各個(gè)節(jié)點(diǎn)開始互相通訊: Nodes configuration updated Sending CLUSTER MEET messages to johe cluster Wai
19、ting for the cluster to join. Performing Cluster Check (using node 127.0.0.1:7000) M: 9991306f0e50640a5684f1958fd754b38fa034c9 127.0.0.1:7000slots:0-5460 (5461 slots) masterM: e68e52cee0550f558b03b342f2f0354d2b8a083b 127.0.0.1:7001slots:5461-10921 (5461 slots) masterM: 393c6df5eb4b4cec323f0e4ca961c8
20、b256e3460a 127.0.0.1:7002 slots:10922-16383 (5462 slots) masterM: 48b728dbcedff6bf056231eb44990b7d1c35c3e0 127.0.0.1:7003S: 3375be2ccc321932e885323487ee9fde973ff 127.0.0.1:7005Can I set the above configuration? (type yes to accept): yes如果一切正常的話, redis-trib 將輸出以下信息:這表示集群中的 16384 個(gè)槽都有至少一個(gè)主節(jié)點(diǎn)在處理, 集群正常。
21、集群的客戶端Redis 集群現(xiàn)階段的一個(gè)問題是客戶端實(shí)現(xiàn)很少。 以下是一些我知道的實(shí)現(xiàn): Check for open slots. Check slots coverage. OK All 16384 slots covered.slots: (0 slots) masterM: 345ede084ac784a5c030a0387f8aaa9edfc59af3 127.0.0.1:7004 slots: (0 slots) masterM: 3375be2ccc321932e885323487ee9fde973ff 127.0.0.1:7005slots: (0 slots) masterO
22、K All nodes agree about slots configuration.測試 Redis 集群比較簡單的辦法就是使用 redis-rb-cluster 或者 redis-cli , 接下來使用 redis-cli 為例來進(jìn)行演示:$ redis-cli -c -p 7000redis 127.0.0.1:7000 set foo bar- Redirected to slot 12182 located at 127.0.0.1:7002 OKredis 127.0.0.1:7002 seto world- Redirected to slot 866 located at 1
23、27.0.0.1:7000 OKredis-rb-cluster 是我(antirez)編寫的 Ruby 實(shí)現(xiàn), 用于作為其他實(shí)現(xiàn)的參考。 該實(shí)現(xiàn)是對 redis-rb 的一個(gè)簡單包裝, 高效地實(shí)現(xiàn)了與集群進(jìn)行通訊所需的最少語義(sem )。redis-py-cluster 看上去是 redis-rb-cluster 的一個(gè) 版本, 這個(gè)項(xiàng)目有一段時(shí)間沒有更新了(最后一次提交是在六個(gè)月之前), 不過可以將這個(gè)項(xiàng)目用作學(xué)習(xí)集群的起點(diǎn)。流行的 Predis 曾經(jīng)對早期的 Redis 集群有過一定的支持, 但我不確定它對集群的支持是否完整, 也不清楚它是否和版本的 Redis 集群兼容 (因?yàn)樾掳娴?/p>
24、 Redis 集群將槽的數(shù)量從 4k 改為 16k 了)。Redis unstable 分支中的 redis-cli 程序?qū)崿F(xiàn)了非?;镜募褐С?, 可以使用命令 redis-cli -c 來啟動(dòng)。redis-cli 對集群的支持是非?;镜?, 所以它總是依靠 Redis 集群節(jié)點(diǎn)來 將它轉(zhuǎn)向(redirect)至正確的節(jié)點(diǎn)。一個(gè)真正的(serious)集群客戶端應(yīng)該做得比這更好: 它應(yīng)該用緩存起哈希槽與節(jié)點(diǎn)地址之間的(map), 從而直接將命令發(fā)送到正確的節(jié)點(diǎn)上面。這種只會(huì)在集群的配置出現(xiàn)某些修改時(shí)變化, 比如說, 在一次故障轉(zhuǎn)移(failover)之后, 或者系統(tǒng)管理員通過添加節(jié)點(diǎn)或移除節(jié)
25、點(diǎn)來修改了集群的布局(layout)之后, 諸如此類。使用 redis-rb-cluster 編寫一個(gè)示例應(yīng)用在展示如何使用集群進(jìn)行故障轉(zhuǎn)移、重新分片等操作之前,需要?jiǎng)?chuàng)建一個(gè)示例應(yīng)用, 了解一些與 Redis 集群客戶端進(jìn)行交互的基本方法。redis 127.0.0.1:7000 get foo- Redirected to slot 12182 located at 127.0.0.1:7002 barredis 127.0.0.1:7000 geto- Redirected to slot 866 located at 127.0.0.1:7000 worldrequire ./clust
26、erstartup_nodes = :host = 127.0.0.1, :port = 7000,:host = 127.0.0.1, :port = 7001rc = RedisCluster.new(startup_nodes,32,:timeout = 0.1)last = false在運(yùn)行示例應(yīng)用的過程中,會(huì)嘗試讓節(jié)點(diǎn)進(jìn)入失效狀態(tài), 又或者開始一次重新分片, 以此來觀察 Redis 集群在真實(shí)世界運(yùn)行時(shí)的表現(xiàn), 并且為了讓這個(gè)示例盡可能地有用,會(huì)讓這個(gè)應(yīng)用向集群進(jìn)行寫操作。本節(jié)將通過兩個(gè)示例應(yīng)用來展示 redis-rb-cluster 的基本用法, 以下是本節(jié)的第一個(gè)示例應(yīng)用, 它是
27、一個(gè)名為 exle.rb 的文件, 包含在 redis-rb- cluster 項(xiàng)目里面:while not lastbeginlast = rc.get( last )last = 0 if!lastrescue = e#e.to_sputs errorsleep 1endend(last.to_i+1).1000000000).each|x|beginrc.set(foo#x,x)puts rc.get(foo#x)代碼中的每個(gè)集群操作都使用一個(gè) begin 和 rescue 代碼塊(block)著, 因?yàn)橄M诖a出錯(cuò)時(shí), 將錯(cuò)誤打印到終端上面, 而不希望應(yīng)用因?yàn)楫?第一個(gè)參數(shù)是了啟動(dòng)節(jié)
28、點(diǎn)的 startup_nodes 列表, 列表中包含了兩個(gè)集群節(jié)點(diǎn) 的地址。第二個(gè)參數(shù)指定了對于集群中的各個(gè)不同的節(jié)點(diǎn), Redis 集群對象可以獲得(take)的最大連接數(shù) (um number of connections this object is allowed to take)。常(exception)而退出。代碼的第七行是代碼中第一個(gè)有趣的地方, 它創(chuàng)建了一個(gè) Redis 集群對象,其中創(chuàng)建對象所使用的參數(shù)及其意義如下:SET foo0 0SET foo1 1SET foo2 2諸如此類。這個(gè)應(yīng)用所做的工作非常簡單: 它不斷地以 foo 為鍵, number 為值, 使用 SET
29、 命令向數(shù)據(jù)庫設(shè)置鍵值對。如果執(zhí)行這個(gè)應(yīng)用的話, 應(yīng)用將按順序執(zhí)行以下命令:rc.set( last ,x) rescue = eputs error #e.to_send sleep 0.1第三個(gè)參數(shù) timeout 指定了一個(gè)命令在執(zhí)行多久之后, 才會(huì)被看作是執(zhí)行失敗。 記住, 啟動(dòng)列表中并不需要包含所有集群節(jié)點(diǎn)的地址, 但這些地址中至少要 有一個(gè)是有效的(reachable): 一旦 redis-rb-cluster 成功連接上集群中的某個(gè)節(jié)點(diǎn)時(shí), 集群節(jié)點(diǎn)列表就會(huì)被自動(dòng)更新, 任何真正的(serious)的集群 ruby ./exle.rb 1234客戶端都應(yīng)該這樣做?,F(xiàn)在, 程序創(chuàng)建
30、的 Redis 集群對象實(shí)例被保存到 rc 變量里面,可以將這個(gè)對象當(dāng)作普通 Redis 對象實(shí)例來使用。在十一至十九行,先嘗試閱讀計(jì)數(shù)器中的值, 如果計(jì)數(shù)器不存在的話,才將計(jì)數(shù)器初始化為 0 : 通過將計(jì)數(shù)值保存到 Redis 的計(jì)數(shù)器里面,可以在示例重啟之后, 仍然繼續(xù)之前的執(zhí)行過程, 而不必每次重啟之后都從 foo0 開始重新設(shè)置鍵值對。為了讓程序在集群下線的情況下, 仍然不斷地嘗試計(jì)數(shù)器的值,操作包含在了一個(gè) while 循環(huán)里面, 一般的應(yīng)用程序并不需要如此。二十一至三十行是程序的主循環(huán), 這個(gè)循環(huán)負(fù)責(zé)設(shè)置鍵值對, 并在設(shè)置出錯(cuò)時(shí)打印錯(cuò)誤信息。程序在主循環(huán)的末尾添加了一個(gè) sleep
31、 調(diào)用, 讓寫操作的執(zhí)行速度變慢, 幫助執(zhí)行示例的人更容易看清程序的輸出。執(zhí)行 exle.rb 程序?qū)a(chǎn)生以下輸出:這個(gè)程序并不是十分有趣, 稍后就會(huì)看到一個(gè)更有趣的集群應(yīng)用示例, $ ./redis-trib.rb reshard 127.0.0.1:7000不過在此之前, 讓先使用這個(gè)示例來演示集群的重新分片操作。對集群進(jìn)行重新分片現(xiàn)在, 讓來試試對集群進(jìn)行重新分片操作。在執(zhí)行重新分片的過程中, 請讓你的 exle.rb 程序處于運(yùn)行狀態(tài), 這樣你就會(huì)看到, 重新分片并不會(huì)對正在運(yùn)行的集群程序產(chǎn)生任何影響, 你也可以考慮將 exle.rb 中的 sleep 調(diào)用刪掉, 從而讓重新分片操作在
32、近乎真實(shí)的寫負(fù)載下執(zhí)行。重新分片操作基本上就是將某些節(jié)點(diǎn)上的哈希槽移動(dòng)到另外一些節(jié)點(diǎn)上面, 和創(chuàng)建集群一樣, 重新分片也可以使用 redis-trib 程序來執(zhí)行。執(zhí)行以下命令可以開始一次重新分片操作:56789.你只需要指定集群中其中一個(gè)節(jié)點(diǎn)的地址, redis-trib 就會(huì)自動(dòng)找到集群中的$ ./redis-trib.rb reshard 127.0.0.1:7000 Connecting to node 127.0.0.1:7000: OK Connecting to node 127.0.0.1:7002: OK Connecting to node 127.0.0.1:7005:
33、OK Connecting to node 127.0.0.1:7001: OK Connecting to node 127.0.0.1:7003: OK Connecting to node 127.0.0.1:7004: OK Performing Cluster Check (using node 127.0.0.1:7000) M: 9991306f0e50640a5684f1958fd754b38fa034c9 127.0.0.1:7000slots:0-5460 (5461 slots) masterM: 393c6df5eb4b4cec323f0e4ca961c8b256e34
34、60a 127.0.0.1:7002其他節(jié)點(diǎn)。目前 redis-trib 只能在管理員的協(xié)助下完成重新分片的工作, 要讓 redis- trib 自動(dòng)將哈希槽從一個(gè)節(jié)點(diǎn)移動(dòng)到另一個(gè)節(jié)點(diǎn), 目前來說還做不到 (不過實(shí)現(xiàn)這個(gè)功能并不難)。執(zhí)行 redis-trib 的第一步就是設(shè)定你打算移動(dòng)的哈希槽的數(shù)量:slots:10922-16383 (5462 slots) masterS: 3375be2ccc321932e885323487ee9fde973ff127.0.0.1:7005slots: (0 slots) slaveM: e68e52cee0550f558b03b342f2f0354d
35、2b8a083b127.0.0.1:7001slots:5461-10921 (5461 slots) masterS: 48b728dbcedff6bf056231eb44990b7d1c35c3e0127.0.0.1:7003slots: (0 slots) slaveS: 345ede084ac784a5c030a0387f8aaa9edfc59af3127.0.0.1:7004slots: (0 slots) slaveOK All nodes agree about slots configuration. Check for open slots. Check slots cove
36、rage.OK All 16384 slots covered.How many slots do you want to move (from 1 to 16384)? 1000接著, redis-trib 會(huì)向你詢問重新分片的源節(jié)點(diǎn)(source node), 也即是,要從哪個(gè)節(jié)點(diǎn)中取出 1000 個(gè)哈希槽, 并將這些槽移動(dòng)到目標(biāo)節(jié)點(diǎn)上面。如果不打算從特定的節(jié)點(diǎn)上取出指定數(shù)量的哈希槽, 那么可以向 redis- trib 輸入 all , 這樣的話, 集群中的所有主節(jié)點(diǎn)都會(huì)成為源節(jié)點(diǎn), redis-$ ./redis-cli -p 7000 cluster nodes | grep mys
37、elf9991306f0e50640a5684f1958fd754b38fa034c9 :0 myself,master - 0 00 connected 0-5460命令來獲得節(jié)點(diǎn)的運(yùn)行 ID :redis-trib 會(huì)打印出集群中所有節(jié)點(diǎn)的 ID , 并且也可以通過執(zhí)行以下$ ./redis-trib.rb reshard 127.0.0.1:7000.What is the receiving node ID? 9991306f0e50640a5684f1958fd754b38fa034c9的話, 現(xiàn)在 1000 個(gè)槽里面應(yīng)該有不少鍵了。除了移動(dòng)的哈希槽數(shù)量之外, redis-trib
38、還需要知道重新分片的目標(biāo)(node), 也即是, 負(fù)責(zé)接收這 1000 個(gè)哈希槽的節(jié)點(diǎn)。指定目標(biāo)需要使用節(jié)點(diǎn)的 ID , 而不是 IP 地址和端口。 比如說,打算使用集群的第一個(gè)主節(jié)點(diǎn)來作為目標(biāo), 它的 IP 地址和端口是 127.0.0.1:7000 , 而節(jié)點(diǎn) ID 則是 9991306f0e50640a5684f1958fd754b38fa034c9 , 那么應(yīng)該向 redis- trib 提供節(jié)點(diǎn)的 ID :打算移動(dòng)的槽數(shù)量設(shè)置為 1000 個(gè), 如果 exle.rb 程序一直運(yùn)行著 輸入 all 并按下回車之后, redis-trib 將打印出哈希槽的移動(dòng)計(jì)劃, 如果你 覺得沒問題的
39、話, 就可以輸入 yes 并再次按下回車:$ ./redis-trib.rb reshard 127.0.0.1:7000.Moving slot 11421 from 393c6df5eb4b4cec323f0e4ca961c8b256e3460a Moving slot 11422 from 393c6df5eb4b4cec323f0e4ca961c8b256e3460a Moving slot 5461 from e68e52cee0550f558b03b342f2f0354d2b8a083b$ ./redis-trib.rb reshard 127.0.0.1:7000.Please
40、enter all the source node IDs.Type all to use all the nodes as source nodes for the hash slots.Type done once you entered all the source nodes IDs.Source node #1:alltrib 將從各個(gè)源節(jié)點(diǎn)中各取出一部分哈希槽, 湊夠 1000 個(gè), 然后移動(dòng)到目標(biāo)節(jié)點(diǎn)上面:$ ./redis-trib.rb reshard 127.0.0.1:7000.Moving slot 5934 from 127.0.0.1:7001 to 127.0.0
41、.1:7000:Moving slot 5935 from 127.0.0.1:7001 to 127.0.0.1:7000:Moving slot 5936 from 127.0.0.1:7001 to 127.0.0.1:7000:Moving slot 5937 from 127.0.0.1:7001 to 127.0.0.1:7000:.Moving slot 5959 from 127.0.0.1:7001 to 127.0.0.1:7000:輸入 yes 并使用按下回車之后, redis-trib 就會(huì)正式開始執(zhí)行重新分片操作, 將指定的哈希槽從源節(jié)點(diǎn)一個(gè)個(gè)地移動(dòng)到目標(biāo)節(jié)點(diǎn)上面:M
42、oving slot 5469 from e68e52cee0550f558b03b342f2f0354d2b8a083b.Moving slot 5959 from e68e52cee0550f558b03b342f2f0354d2b8a083bDo you want to proceed with the proed reshard plan (yes/no)? yes在重新分片的過程中, exle.rb 應(yīng)該可以繼續(xù)正常運(yùn)行, 不會(huì)出現(xiàn)任何問 $ ./redis-trib.rb check 127.0.0.1:7000 Connecting to node 127.0.0.1:7000:
43、 OK Connecting to node 127.0.0.1:7002: OK Connecting to node 127.0.0.1:7005: OK Connecting to node 127.0.0.1:7001: OK Connecting to node 127.0.0.1:7003: OK Connecting to node 127.0.0.1:7004: OK Performing Cluster Check (using node 127.0.0.1:7000) M: 9991306f0e50640a5684f1958fd754b38fa034c9 127.0.0.1
44、:7000slots:0-5959,10922-11422 (6461 slots) masterM: 393c6df5eb4b4cec323f0e4ca961c8b256e3460a 127.0.0.1:7002 slots:11423-16383 (4961 slots) master題。在重新分片操作執(zhí)行完畢之后, 可以使用以下命令來檢查集群是否正常:根據(jù)檢查結(jié)果顯示, 集群正常。需要注意的就是, 在三個(gè)主節(jié)點(diǎn)中, 節(jié)點(diǎn) 127.0.0.1:7000 包含了 6461 個(gè)哈希槽, 而節(jié)點(diǎn) 127.0.0.1:7001 和節(jié)點(diǎn) 127.0.0.1:7002 都只包含了 4961 個(gè)哈希槽,
45、 因?yàn)楹髢烧叨紝⒆约旱?500 個(gè)哈希槽移動(dòng)到了節(jié)點(diǎn) 127.0.0.1:7000 。S: 3375be2ccc321932e885323487ee9fde973ff 127.0.0.1:7005slots: (0 slots) slaveM: e68e52cee0550f558b03b342f2f0354d2b8a083b 127.0.0.1:7001slots:5960-10921 (4962 slots) masterS: 48b728dbcedff6bf056231eb44990b7d1c35c3e0 127.0.0.1:7003 slots: (0 slots) slaveS: 34
46、5ede084ac784a5c030a0387f8aaa9edfc59af3 127.0.0.1:7004 slots: (0 slots) slaveOK All nodes agree about slots configuration. Check for open slots. Check slots coverage. OK All 16384 slots covered.種情況中, consistency-test.rb的計(jì)數(shù)器值將比集群的計(jì)數(shù)器值要 $ ruby consistency-test.rb925 R (0 err) | 925 W (0 err) |5030 R (0
47、 err) | 5030 W (0 err) |9261 R (0 err) | 9261 W (0 err) |的計(jì)數(shù)器值要小。運(yùn)行 consistency-test 程序?qū)a(chǎn)生類似以下的輸出:大; 而在后一種情況中, consistency-test.rb的計(jì)數(shù)器值將比集群換句話說, 這個(gè)程序是一個(gè)一致性檢查器(consistency checker): 如果集群在執(zhí)行 INCR 命令的過程中, 丟失了某條 INCR 命令, 又或者多執(zhí)行了某條客戶端沒有確認(rèn)到的 INCR 命令, 那么檢查器將察覺到這一點(diǎn) 一每次使用 INCR 命令更新一個(gè)計(jì)數(shù)器時(shí), 應(yīng)用會(huì)下計(jì)數(shù)器執(zhí)行 INCR 命令之后
48、應(yīng)該有的值。 舉個(gè)例子, 如果計(jì)數(shù)器的起始值為 0 , 而這次是程序第 50 次向它發(fā)送 INCR 命令, 那么計(jì)數(shù)器的值應(yīng)該是 50 。在每次發(fā)送 INCR 命令之前, 程序會(huì)隨機(jī)從集群中一個(gè)計(jì)數(shù)器的值, 并將它與自己的值進(jìn)行對比, 看兩個(gè)值是否相同。一個(gè)更有趣的示例應(yīng)用面使用的示例程序 exle.rb 并不是十分有趣, 因?yàn)樗皇遣粩嗟貙哼M(jìn)行寫入, 但并查寫入結(jié)果是否正確。 比如說, 集群可能會(huì)錯(cuò)誤地將 exle.rb 發(fā)送的所有 SET 命令都改成了 SETfoo 42 , 但因?yàn)?exle.rb 并查寫入后的值, 所以它不會(huì)集群實(shí)際上寫入的值是錯(cuò)誤的。因?yàn)檫@個(gè)原因, redis-r
49、b-cluster 項(xiàng)目包含了一個(gè)名為 consistency-test.rb 的示例應(yīng)用, 這個(gè)應(yīng)用比起 exle.rb 有趣得多: 它創(chuàng)建了多個(gè)計(jì)數(shù)器(默認(rèn)為 1000 個(gè)), 并通過發(fā)送 INCR 命令來增加這些計(jì)數(shù)器的值。在增加計(jì)數(shù)器值的同時(shí), consistency-test.rb 還執(zhí)行以下操作:每行輸出都打印了程序執(zhí)行的次數(shù)和寫入次數(shù), 以及執(zhí)行操作的過程中因那么 consistency-test.rb 將向不一致情況:(he other tab I see.)94774 R (0 err) | 94774 W (0 err) |98821 R (0 err) | 98821 W
50、 (0 err) |$ redis 127.0.0.1:7000 set key_217 0OK為集群不可用而產(chǎn)生的錯(cuò)誤數(shù)。如果程序察覺了不一致的情況出現(xiàn), 它將在輸出行的末尾顯式不一致的詳細(xì)情況。比如說, 如果在 consistency-test.rb 運(yùn)行的過程中, 手動(dòng)修改某個(gè)計(jì)數(shù)器的值:13517 R (0 err) | 13517 W (0 err) |17780 R (0 err) | 17780 W (0 err) |22025 R (0 err) | 22025 W (0 err) |25818 R (0 err) | 25818 W (0 err) |在修改計(jì)數(shù)器值的時(shí)候,
51、計(jì)數(shù)器的正確值是 114 (執(zhí)行了 114 次 INCR 命令), 因?yàn)橛?jì)數(shù)器的值設(shè)成了 0 , 所以$ 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-16
52、383consistency-test.rb 會(huì)向說丟失了 114 個(gè) INCR 命令。因?yàn)檫@個(gè)示例程序具有一致性檢查功能, 所以用它來測試 Redis 集群的故障轉(zhuǎn)移操作。故障轉(zhuǎn)移測試在執(zhí)行本節(jié)操作的過程中, 請一直運(yùn)行 consistency-test 程序。要觸發(fā)一次故障轉(zhuǎn)移, 最簡單的辦法就是令集群中的某個(gè)主節(jié)點(diǎn)進(jìn)入下線狀態(tài)。首先用以下命令列出集群中的所有主節(jié)點(diǎn):102886 R (0 err) | 102886 W (0 err) | 114 lost |107046 R (0 err) | 107046 W (0 err) | 114 lost |然后可以通過向端為 7002 的主
53、節(jié)點(diǎn)發(fā)送 DEBUG SEGFAULT 命令, 讓這個(gè)主節(jié)點(diǎn):現(xiàn)在, 切換到運(yùn)行著 consistency-test 的頁, 可以看 到, consistency-test 在 7002 下線之后的一段時(shí)間里將產(chǎn)生大量的錯(cuò)誤警告 信息: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) |$ redis-cl
54、i -p 7002 debug segfaultError: Server closed the connection通過命令輸出,知道端為 7000 、 7001 和 7002 的節(jié)點(diǎn)都是主節(jié)點(diǎn), 97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master - 0 00 connected 0-5959 10922-11422從 consistency-test 的這段輸出可以看到, 集群在執(zhí)行故障轉(zhuǎn)移期間, 總共$ redis-cli -p 7000 cluster nodes3fc783611028b1707fd65345e763b
55、efb36454d73 127.0.0.1:7004 slave3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 0 1385503418521 0connecteda211e242fc6b22a9427fed61285e85892fa04e08 127.0.0.1:7003 slave97a3a64667477371c4479320d683e4c8db5858b1 0 1385503419023 0connected丟失了 578 個(gè)讀命令和 577 個(gè)寫命令, 但是并沒有產(chǎn)生任何數(shù)據(jù)不一致。這聽上去可能有點(diǎn)奇怪, 因?yàn)樵诘拈_頭提到過, Redis 使用的是異
56、步, 在執(zhí)行故障轉(zhuǎn)移期間, 集群可能會(huì)丟失寫命令。但是在實(shí)際上, 丟失命令的情況并不常見, 因?yàn)?Redis 幾乎是同時(shí)執(zhí)行將命令回復(fù)發(fā)送給客戶端, 以及將命令給從節(jié)點(diǎn)這兩個(gè)操作, 所以實(shí)際上造成命令丟失的時(shí)間窗口是非常小的。不過, 盡管出現(xiàn)的幾率不高, 但丟失命令的情況還是有可能會(huì)出現(xiàn)的, 所以對 Redis 集群不能提供強(qiáng)一致性的這一描述仍然是正確的?,F(xiàn)在, 讓使用 cluster nodes 命令, 查看集群在執(zhí)行故障轉(zhuǎn)移操作之后, 主從節(jié)點(diǎn)的布局情況:33749 R (578 err) | 33750 W (577 err) |37918 R (578 err) | 37919 W (
57、577 err) |42077 R (578 err) | 42078 W (577 err) |節(jié)點(diǎn) ID :例如 3fc783611028b1707fd65345e763befb36454d73 。ip:port :節(jié)點(diǎn)的 IP 地址和端, 例如 127.0.0.1:7000 , 其中 :0 表示的是客戶端當(dāng)前連接的 IP 地址和端。flags :節(jié)點(diǎn)的角色(例如 master 、 slave 、 myself )以及狀態(tài)(例如 fail ,等等)。如果節(jié)點(diǎn)是一個(gè)從節(jié)點(diǎn)的話, 那么跟在 flags 之后的將是主節(jié)點(diǎn)的節(jié)點(diǎn) ID : 例如 127.0.0.1:7002 的主節(jié)點(diǎn)的節(jié)點(diǎn) ID
58、就是3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 。集群最近一次向節(jié)點(diǎn)發(fā)送命令之后, 過去了多長時(shí)間還沒接到回復(fù)。節(jié)點(diǎn)最近一次返回 PONG 回復(fù)的時(shí)間。節(jié)點(diǎn)的配置(configuration epoch):詳細(xì)信息請參考 Redis 集群規(guī)范 。我重啟了之前下線的 127.0.0.1:7002 節(jié)點(diǎn), 該節(jié)點(diǎn)已經(jīng)從原來的主節(jié)點(diǎn)變成了從節(jié)點(diǎn), 而現(xiàn)在集群中的三個(gè)主節(jié)點(diǎn)分別是 127.0.0.1:7000、 127.0.0.1:7001 和 127.0.0.1:7005 , 其中 127.0.0.1:7005 就是因?yàn)?127.0.0.1:7002 下線而變成
59、主節(jié)點(diǎn)的。clusternodes 命令的輸出有點(diǎn)兒復(fù)雜, 它的每一行都是由以下信息組成的:97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master - 0 00 connected 0-5959 10922-114223c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7005 master- 0 1385503419023 3 connected 11423-163833e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 ma
60、ster- 0 1385503417005 0 connected 5960-109212938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 slave3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385503418016 3 connected./redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000如果一切正常, 那么節(jié)點(diǎn)應(yīng)該會(huì)正確地啟動(dòng)。接下來, 執(zhí)行以下命令, 將這個(gè)新節(jié)點(diǎn)添加到集群里面:在終端里創(chuàng)建一個(gè)新的頁。進(jìn)入 cluster-te
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 湖南第一師范學(xué)院《世界近代史專題》2023-2024學(xué)年第二學(xué)期期末試卷
- 浙江育英職業(yè)技術(shù)學(xué)院《特殊兒童心理學(xué)》2023-2024學(xué)年第二學(xué)期期末試卷
- 做賬實(shí)操-駕校教練人工成本的核算
- 2024-2025學(xué)年河南省名校大聯(lián)考高二上學(xué)期階段性測試(二)歷史試卷
- 大連工業(yè)大學(xué)《產(chǎn)品色彩設(shè)計(jì)》2023-2024學(xué)年第二學(xué)期期末試卷
- 電子科技大學(xué)中山學(xué)院《建筑裝飾材料》2023-2024學(xué)年第二學(xué)期期末試卷
- 洛陽理工學(xué)院《工商管理類專業(yè)導(dǎo)論》2023-2024學(xué)年第二學(xué)期期末試卷
- 渭南職業(yè)技術(shù)學(xué)院《醫(yī)學(xué)網(wǎng)站開發(fā)》2023-2024學(xué)年第二學(xué)期期末試卷
- 陽泉職業(yè)技術(shù)學(xué)院《現(xiàn)代冶金學(xué)》2023-2024學(xué)年第二學(xué)期期末試卷
- 山西水利職業(yè)技術(shù)學(xué)院《市場營銷學(xué)》2023-2024學(xué)年第二學(xué)期期末試卷
- 2025年工貿(mào)企業(yè)春節(jié)復(fù)工復(fù)產(chǎn)方案
- FZ/T 07010-2021綠色設(shè)計(jì)產(chǎn)品評價(jià)技術(shù)規(guī)范針織服裝
- 公路工程工程量清單第章解析及計(jì)量支付
- API-650-1鋼制焊接石油儲(chǔ)罐
- 湖南省普通高中畢業(yè)生登記表模板
- 人教版七年級上冊數(shù)學(xué)試卷全冊
- 中職-中國歷史教案
- 六年級小升初語文試卷 [六年級下冊語文小升初試卷
- 計(jì)量泵的維護(hù)和修理知識培訓(xùn)講義
- 危險(xiǎn)化學(xué)品從業(yè)單位安全生產(chǎn)標(biāo)準(zhǔn)化宣貫
- 幼兒園中班開學(xué)第一課
評論
0/150
提交評論