日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Redis集群教程

發(fā)布時(shí)間:2025/3/21 数据库 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis集群教程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Redis集群教程

本文檔翻譯自?http://redis.io/topics/cluster-tutorial?。

本文檔是 Redis 集群的入門教程, 從用戶的角度介紹了設(shè)置、測(cè)試和操作集群的方法。

本教程不包含晦澀難懂的分布式概念, 也沒有像?Redis 集群規(guī)范?那樣包含 Redis 集群的實(shí)現(xiàn)細(xì)節(jié), 如果你打算深入地學(xué)習(xí) Redis 集群的部署方法, 那么推薦你在閱讀完這個(gè)教程之后, 再去看一看集群規(guī)范。

Redis 集群目前仍處于 Alpha 測(cè)試版本, 如果在使用過程中發(fā)現(xiàn)任何問題, 請(qǐng)到?Redis 的郵件列表?發(fā)貼, 或者到?Redis 的 Github 頁面?報(bào)告錯(cuò)誤。

集群簡(jiǎn)介

Redis 集群是一個(gè)可以在多個(gè) Redis 節(jié)點(diǎn)之間進(jìn)行數(shù)據(jù)共享的設(shè)施(installation)。

Redis 集群不支持那些需要同時(shí)處理多個(gè)鍵的 Redis 命令, 因?yàn)閳?zhí)行這些命令需要在多個(gè) Redis 節(jié)點(diǎn)之間移動(dòng)數(shù)據(jù), 并且在高負(fù)載的情況下, 這些命令將降低 Redis 集群的性能, 并導(dǎo)致不可預(yù)測(cè)的行為。

Redis 集群通過分區(qū)(partition)來提供一定程度的可用性(availability): 即使集群中有一部分節(jié)點(diǎn)失效或者無法進(jìn)行通訊, 集群也可以繼續(xù)處理命令請(qǐng)求。

Redis 集群提供了以下兩個(gè)好處:

  • 將數(shù)據(jù)自動(dòng)切分(split)到多個(gè)節(jié)點(diǎn)的能力。
  • 當(dāng)集群中的一部分節(jié)點(diǎn)失效或者無法進(jìn)行通訊時(shí), 仍然可以繼續(xù)處理命令請(qǐng)求的能力。

Redis 集群數(shù)據(jù)共享

Redis 集群使用數(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) A 負(fù)責(zé)處理?0?號(hào)至?5500?號(hào)哈希槽。
  • 節(jié)點(diǎn) B 負(fù)責(zé)處理?5501?號(hào)至?11000?號(hào)哈希槽。
  • 節(jié)點(diǎn) C 負(fù)責(zé)處理?11001?號(hào)至?16384?號(hào)哈希槽。

這種將哈希槽分布到不同節(jié)點(diǎn)的做法使得用戶可以很容易地向集群中添加或者刪除節(jié)點(diǎn)。 比如說:

  • 如果用戶將新節(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 就可以了。

因?yàn)閷⒁粋€(gè)哈希槽從一個(gè)節(jié)點(diǎn)移動(dòng)到另一個(gè)節(jié)點(diǎn)不會(huì)造成節(jié)點(diǎn)阻塞, 所以無論是添加新節(jié)點(diǎn)還是移除已存在節(jié)點(diǎn), 又或者改變某個(gè)節(jié)點(diǎn)包含的哈希槽數(shù)量, 都不會(huì)造成集群下線。

Redis 集群中的主從復(fù)制

為了使得集群在一部分節(jié)點(diǎn)下線或者無法與集群的大多數(shù)(majority)節(jié)點(diǎn)進(jìn)行通訊的情況下, 仍然可以正常運(yùn)作, Redis 集群對(duì)節(jié)點(diǎn)使用了主從復(fù)制功能: 集群中的每個(gè)節(jié)點(diǎn)都有?1?個(gè)至?N?個(gè)復(fù)制品(replica), 其中一個(gè)復(fù)制品為主節(jié)點(diǎn)(master), 而其余的?N-1?個(gè)復(fù)制品為從節(jié)點(diǎn)(slave)。

在之前列舉的節(jié)點(diǎn) A 、B 、C 的例子中, 如果節(jié)點(diǎn) B 下線了, 那么集群將無法正常運(yùn)行, 因?yàn)榧赫也坏焦?jié)點(diǎn)來處理?5501?號(hào)至?11000?號(hào)的哈希槽。

另一方面, 假如在創(chuàng)建集群的時(shí)候(或者至少在節(jié)點(diǎn) B 下線之前), 我們?yōu)橹鞴?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?號(hào)至?11000?號(hào)的哈希槽, 這樣集群就不會(huì)因?yàn)橹鞴?jié)點(diǎn) B 的下線而無法正常運(yùn)作了。

不過如果節(jié)點(diǎn) B 和 B1 都下線的話, Redis 集群還是會(huì)停止運(yùn)作。

Redis 集群的一致性保證(guarantee)

Redis 集群不保證數(shù)據(jù)的強(qiáng)一致性(strong consistency): 在特定條件下, Redis 集群可能會(huì)丟失已經(jīng)被執(zhí)行過的寫命令。

使用異步復(fù)制(asynchronous replication)是 Redis 集群可能會(huì)丟失寫命令的其中一個(gè)原因。 考慮以下這個(gè)寫命令的例子:

  • 客戶端向主節(jié)點(diǎn) B 發(fā)送一條寫命令。
  • 主節(jié)點(diǎn) B 執(zhí)行寫命令,并向客戶端返回命令回復(fù)。
  • 主節(jié)點(diǎn) B 將剛剛執(zhí)行的寫命令復(fù)制給它的從節(jié)點(diǎn) B1 、 B2 和 B3 。

如你所見, 主節(jié)點(diǎn)對(duì)命令的復(fù)制工作發(fā)生在返回命令回復(fù)之后, 因?yàn)槿绻看翁幚砻钫?qǐng)求都需要等待復(fù)制操作完成的話, 那么主節(jié)點(diǎn)處理命令請(qǐng)求的速度將極大地降低 —— 我們必須在性能和一致性之間做出權(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ù)(majority)的一方包含節(jié)點(diǎn) A 、C 、A1 、B1 和 C1 , 而少數(shù)(minority)的一方則包含節(jié)點(diǎn) B 和客戶端 Z1 。

在網(wǎng)絡(luò)分裂期間, 主節(jié)點(diǎn) B 仍然會(huì)接受 Z1 發(fā)送的寫命令:

  • 如果網(wǎng)絡(luò)分裂出現(xiàn)的時(shí)間很短, 那么集群會(huì)繼續(xù)正常運(yùn)行;
  • 但是, 如果網(wǎng)絡(luò)分裂出現(xiàn)的時(shí)間足夠長(zhǎng), 使得大多數(shù)一方將從節(jié)點(diǎn) B1 設(shè)置為新的主節(jié)點(diǎn), 并使用 B1 來代替原來的主節(jié)點(diǎn) B , 那么 Z1 發(fā)送給主節(jié)點(diǎn) B 的寫命令將丟失。

注意, 在網(wǎng)絡(luò)分裂出現(xiàn)期間, 客戶端 Z1 可以向主節(jié)點(diǎn) B 發(fā)送寫命令的最大時(shí)間是有限制的, 這一時(shí)間限制稱為節(jié)點(diǎn)超時(shí)時(shí)間(node timeout), 是 Redis 集群的一個(gè)重要的配置選項(xiàng):

  • 對(duì)于大多數(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é)點(diǎn)繼續(xù)工作。
  • 對(duì)于少數(shù)一方, 如果一個(gè)主節(jié)點(diǎn)未能在節(jié)點(diǎn)超時(shí)時(shí)間所設(shè)定的時(shí)限內(nèi)重新聯(lián)系上集群, 那么它將停止處理寫命令, 并向客戶端報(bào)告錯(cuò)誤。

創(chuàng)建并使用 Redis 集群

Redis 集群由多個(gè)運(yùn)行在集群模式(cluster mode)下的 Redis 實(shí)例組成, 實(shí)例的集群模式需要通過配置來開啟, 開啟集群模式的實(shí)例將可以使用集群特有的功能和命令。

以下是一個(gè)包含了最少選項(xiàng)的集群配置文件示例:

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

文件中的?cluster-enabled?選項(xiàng)用于開實(shí)例的集群模式, 而?cluster-conf-file?選項(xiàng)則設(shè)定了保存節(jié)點(diǎn)配置文件的路徑, 默認(rèn)值為?nodes.conf?。

節(jié)點(diǎn)配置文件無須人為修改, 它由 Redis 集群在啟動(dòng)時(shí)創(chuàng)建, 并在有需要時(shí)自動(dòng)進(jìn)行更新。

要讓集群正常運(yù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è)以端口號(hào)為名字的子目錄, 稍后我們?cè)趯⒚總€(gè)目錄中運(yùn)行一個(gè) Redis 實(shí)例:

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

在文件夾?7000?至?7005?中, 各創(chuàng)建一個(gè)?redis.conf?文件, 文件的內(nèi)容可以使用上面的示例配置文件, 但記得將配置中的端口號(hào)從?7000?改為與文件夾名字相同的號(hào)碼。

現(xiàn)在, 從?Redis Github 頁面?的?unstable?分支中取出最新的 Redis 源碼, 編譯出可執(zhí)行文件?redis-server?, 并將文件復(fù)制到?cluster-test文件夾, 然后使用類似以下命令,? 在每個(gè)標(biāo)簽頁中打開一個(gè)實(shí)例:

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

實(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

實(shí)例會(huì)一直使用同一個(gè) ID , 從而在集群中保持一個(gè)獨(dú)一無二(unique)的名字。

每個(gè)節(jié)點(diǎn)都使用 ID 而不是 IP 或者端口號(hào)來記錄其他節(jié)點(diǎn), 因?yàn)?IP 地址和端口號(hào)都可能會(huì)改變, 而這個(gè)獨(dú)一無二的標(biāo)識(shí)符(identifier)則會(huì)在節(jié)點(diǎn)的整個(gè)生命周期中一直保持不變。

我們將這個(gè)標(biāo)識(shí)符稱為節(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è) Ruby 程序, 這個(gè)程序通過向?qū)嵗l(fā)送特殊命令來完成創(chuàng)建新集群, 檢查集群, 或者對(duì)集群進(jìn)行重新分片(reshared)等工作。

我們需要執(zhí)行以下命令來創(chuàng)建集群:

./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

命令的意義如下:

  • 給定?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)建新集群。

簡(jiǎn)單來說, 以上命令的意思就是讓?redis-trib?程序創(chuàng)建一個(gè)包含三個(gè)主節(jié)點(diǎn)和三個(gè)從節(jié)點(diǎn)的集群。

接著,?redis-trib?會(huì)打印出一份預(yù)想中的配置給你看, 如果你覺得沒問題的話, 就可以輸入?yes?,?redis-trib?就會(huì)將這份配置應(yīng)用到集群當(dāng)中:

>>> Creating cluster Connecting to node 127.0.0.1:7000: OK Connecting 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: 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7000 replica #1 is 127.0.0.1:7003 127.0.0.1:7001 replica #1 is 127.0.0.1:7004 127.0.0.1:7002 replica #1 is 127.0.0.1:7005 M: 9991306f0e50640a5684f1958fd754b38fa034c9 127.0.0.1:7000 slots:0-5460 (5461 slots) master M: e68e52cee0550f558b03b342f2f0354d2b8a083b 127.0.0.1:7001 slots:5461-10921 (5461 slots) master M: 393c6df5eb4b4cec323f0e4ca961c8b256e3460a 127.0.0.1:7002 slots:10922-16383 (5462 slots) master S: 48b728dbcedff6bf056231eb44990b7d1c35c3e0 127.0.0.1:7003 S: 345ede084ac784a5c030a0387f8aaa9edfc59af3 127.0.0.1:7004 S: 3375be2ccc321932e8853234ffa87ee9fde973ff 127.0.0.1:7005 Can I set the above configuration? (type 'yes' to accept): yes

輸入?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 join the cluster Waiting for the cluster to join... >>> Performing Cluster Check (using node 127.0.0.1:7000) M: 9991306f0e50640a5684f1958fd754b38fa034c9 127.0.0.1:7000 slots:0-5460 (5461 slots) master M: e68e52cee0550f558b03b342f2f0354d2b8a083b 127.0.0.1:7001 slots:5461-10921 (5461 slots) master M: 393c6df5eb4b4cec323f0e4ca961c8b256e3460a 127.0.0.1:7002 slots:10922-16383 (5462 slots) master M: 48b728dbcedff6bf056231eb44990b7d1c35c3e0 127.0.0.1:7003 slots: (0 slots) master M: 345ede084ac784a5c030a0387f8aaa9edfc59af3 127.0.0.1:7004 slots: (0 slots) master M: 3375be2ccc321932e8853234ffa87ee9fde973ff 127.0.0.1:7005 slots: (0 slots) master [OK] All nodes agree about slots configuration.

如果一切正常的話,?redis-trib?將輸出以下信息:

>>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.

這表示集群中的?16384?個(gè)槽都有至少一個(gè)主節(jié)點(diǎn)在處理, 集群運(yùn)作正常。

集群的客戶端

Redis 集群現(xiàn)階段的一個(gè)問題是客戶端實(shí)現(xiàn)很少。 以下是一些我知道的實(shí)現(xiàn):

  • redis-rb-cluster?是我(@antirez)編寫的 Ruby 實(shí)現(xiàn), 用于作為其他實(shí)現(xiàn)的參考。 該實(shí)現(xiàn)是對(duì)?redis-rb?的一個(gè)簡(jiǎn)單包裝, 高效地實(shí)現(xiàn)了與集群進(jìn)行通訊所需的最少語義(semantic)。
  • redis-py-cluster?看上去是?redis-rb-cluster?的一個(gè) Python 版本, 這個(gè)項(xiàng)目有一段時(shí)間沒有更新了(最后一次提交是在六個(gè)月之前), 不過可以將這個(gè)項(xiàng)目用作學(xué)習(xí)集群的起點(diǎn)。
  • 流行的 Predis 曾經(jīng)對(duì)早期的 Redis 集群有過一定的支持, 但我不確定它對(duì)集群的支持是否完整, 也不清楚它是否和最新版本的 Redis 集群兼容 (因?yàn)樾掳娴?Redis 集群將槽的數(shù)量從 4k 改為 16k 了)。
  • Redis?unstable?分支中的?redis-cli?程序?qū)崿F(xiàn)了非?;镜募褐С?#xff0c; 可以使用命令?redis-cli?-c?來啟動(dòng)。

測(cè)試 Redis 集群比較簡(jiǎn)單的辦法就是使用?redis-rb-cluster?或者?redis-cli?, 接下來我們將使用?redis-cli?為例來進(jìn)行演示:

$ 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 OKredis 127.0.0.1:7002> set hello world -> Redirected to slot [866] located at 127.0.0.1:7000 OKredis 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?對(duì)集群的支持是非常基本的, 所以它總是依靠 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é)點(diǎn)來修改了集群的布局(layout)之后, 諸如此類。

使用?redis-rb-cluster?編寫一個(gè)示例應(yīng)用

在展示如何使用集群進(jìn)行故障轉(zhuǎn)移、重新分片等操作之前, 我們需要?jiǎng)?chuàng)建一個(gè)示例應(yīng)用, 了解一些與 Redis 集群客戶端進(jìn)行交互的基本方法。

在運(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)用, 它是一個(gè)名為?example.rb?的文件, 包含在redis-rb-cluster 項(xiàng)目里面:

123456789 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 require './cluster'startup_nodes = [{:host => "127.0.0.1", :port => 7000},{:host => "127.0.0.1", :port => 7001} ] rc = RedisCluster.new(startup_nodes,32,:timeout => 0.1)last = falsewhile not lastbeginlast = rc.get("__last__")last = 0 if !lastrescue => eputs "error #{e.to_s}"sleep 1end end((last.to_i+1)..1000000000).each{|x|beginrc.set("foo#{x}",x)puts rc.get("foo#{x}")rc.set("__last__",x)rescue => eputs "error #{e.to_s}"endsleep 0.1 }

這個(gè)應(yīng)用所做的工作非常簡(jiǎn)單: 它不斷地以?foo<number>?為鍵,?number?為值, 使用?SET?命令向數(shù)據(jù)庫設(shè)置鍵值對(duì)。

如果我們執(zhí)行這個(gè)應(yīng)用的話, 應(yīng)用將按順序執(zhí)行以下命令:

  • SET?foo0?0
  • SET?foo1?1
  • SET?foo2?2
  • 諸如此類。。。

代碼中的每個(gè)集群操作都使用一個(gè)?begin?和?rescue?代碼塊(block)包裹著, 因?yàn)槲覀兿M诖a出錯(cuò)時(shí), 將錯(cuò)誤打印到終端上面, 而不希望應(yīng)用因?yàn)楫惓?#xff08;exception)而退出。

代碼的第七行是代碼中第一個(gè)有趣的地方, 它創(chuàng)建了一個(gè) Redis 集群對(duì)象, 其中創(chuàng)建對(duì)象所使用的參數(shù)及其意義如下:

  • 第一個(gè)參數(shù)是記錄了啟動(dòng)節(jié)點(diǎn)的?startup_nodes?列表, 列表中包含了兩個(gè)集群節(jié)點(diǎn)的地址。
  • 第二個(gè)參數(shù)指定了對(duì)于集群中的各個(gè)不同的節(jié)點(diǎn), Redis 集群對(duì)象可以獲得(take)的最大連接數(shù) (maximum number of connections this object is allowed to take)。
  • 第三個(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)的集群客戶端都應(yīng)該這樣做。

現(xiàn)在, 程序創(chuàng)建的 Redis 集群對(duì)象實(shí)例被保存到?rc?變量里面, 我們可以將這個(gè)對(duì)象當(dāng)作普通 Redis 對(duì)象實(shí)例來使用。

十一至十九行, 我們先嘗試閱讀計(jì)數(shù)器中的值, 如果計(jì)數(shù)器不存在的話, 我們才將計(jì)數(shù)器初始化為?0?: 通過將計(jì)數(shù)值保存到 Redis 的計(jì)數(shù)器里面, 我們可以在示例重啟之后, 仍然繼續(xù)之前的執(zhí)行過程, 而不必每次重啟之后都從?foo0?開始重新設(shè)置鍵值對(duì)。

為了讓程序在集群下線的情況下, 仍然不斷地嘗試讀取計(jì)數(shù)器的值, 我們將讀取操作包含在了一個(gè)?while?循環(huán)里面, 一般的應(yīng)用程序并不需要如此小心。

二十一至三十行是程序的主循環(huán), 這個(gè)循環(huán)負(fù)責(zé)設(shè)置鍵值對(duì), 并在設(shè)置出錯(cuò)時(shí)打印錯(cuò)誤信息。

程序在主循環(huán)的末尾添加了一個(gè)?sleep?調(diào)用, 讓寫操作的執(zhí)行速度變慢, 幫助執(zhí)行示例的人更容易看清程序的輸出。

執(zhí)行?example.rb?程序?qū)a(chǎn)生以下輸出:

ruby ./example.rb 1 2 3 4 5 6 7 8 9 ...

這個(gè)程序并不是十分有趣, 稍后我們就會(huì)看到一個(gè)更有趣的集群應(yīng)用示例, 不過在此之前, 讓我們先使用這個(gè)示例來演示集群的重新分片操作。

對(duì)集群進(jìn)行重新分片

現(xiàn)在, 讓我們來試試對(duì)集群進(jìn)行重新分片操作。

在執(zhí)行重新分片的過程中, 請(qǐng)讓你的?example.rb?程序處于運(yùn)行狀態(tài), 這樣你就會(huì)看到, 重新分片并不會(huì)對(duì)正在運(yùn)行的集群程序產(chǎn)生任何影響, 你也可以考慮將?example.rb?中的?sleep?調(diào)用刪掉, 從而讓重新分片操作在近乎真實(shí)的寫負(fù)載下執(zhí)行。

重新分片操作基本上就是將某些節(jié)點(diǎn)上的哈希槽移動(dòng)到另外一些節(jié)點(diǎn)上面, 和創(chuàng)建集群一樣, 重新分片也可以使用?redis-trib?程序來執(zhí)行。

執(zhí)行以下命令可以開始一次重新分片操作:

$ ./redis-trib.rb reshard 127.0.0.1:7000

你只需要指定集群中其中一個(gè)節(jié)點(diǎn)的地址,?redis-trib?就會(huì)自動(dòng)找到集群中的其他節(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ù)量:

$ ./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: 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:7000 slots:0-5460 (5461 slots) master M: 393c6df5eb4b4cec323f0e4ca961c8b256e3460a 127.0.0.1:7002 slots:10922-16383 (5462 slots) master S: 3375be2ccc321932e8853234ffa87ee9fde973ff 127.0.0.1:7005 slots: (0 slots) slave M: e68e52cee0550f558b03b342f2f0354d2b8a083b 127.0.0.1:7001 slots:5461-10921 (5461 slots) master S: 48b728dbcedff6bf056231eb44990b7d1c35c3e0 127.0.0.1:7003 slots: (0 slots) slave S: 345ede084ac784a5c030a0387f8aaa9edfc59af3 127.0.0.1:7004 slots: (0 slots) slave [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. How many slots do you want to move (from 1 to 16384)? 1000

我們將打算移動(dòng)的槽數(shù)量設(shè)置為?1000?個(gè), 如果?example.rb?程序一直運(yùn)行著的話, 現(xiàn)在?1000?個(gè)槽里面應(yīng)該有不少鍵了。

除了移動(dòng)的哈希槽數(shù)量之外,?redis-trib?還需要知道重新分片的目標(biāo)(target 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 :

$ ./redis-trib.rb reshard 127.0.0.1:7000 ... What is the receiving node ID? 9991306f0e50640a5684f1958fd754b38fa034c9

redis-trib?會(huì)打印出集群中所有節(jié)點(diǎn)的 ID , 并且我們也可以通過執(zhí)行以下命令來獲得節(jié)點(diǎn)的運(yùn)行 ID :

$ ./redis-cli -p 7000 cluster nodes | grep myself 9991306f0e50640a5684f1958fd754b38fa034c9 :0 myself,master - 0 0 0 connected 0-5460

接著,?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-trib?將從各個(gè)源節(jié)點(diǎn)中各取出一部分哈希槽, 湊夠?1000?個(gè), 然后移動(dòng)到目標(biāo)節(jié)點(diǎn)上面:

$ ./redis-trib.rb reshard 127.0.0.1:7000 ... Please 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:all

輸入?all?并按下回車之后,?redis-trib?將打印出哈希槽的移動(dòng)計(jì)劃, 如果你覺得沒問題的話, 就可以輸入?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 Moving slot 5469 from e68e52cee0550f558b03b342f2f0354d2b8a083b ... Moving slot 5959 from e68e52cee0550f558b03b342f2f0354d2b8a083b Do you want to proceed with the proposed reshard plan (yes/no)? yes

輸入?yes?并使用按下回車之后,?redis-trib?就會(huì)正式開始執(zhí)行重新分片操作, 將指定的哈希槽從源節(jié)點(diǎn)一個(gè)個(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.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:

在重新分片的過程中,?example.rb?應(yīng)該可以繼續(xù)正常運(yùn)行, 不會(huì)出現(xiàn)任何問題。

在重新分片操作執(zhí)行完畢之后, 可以使用以下命令來檢查集群是否正常:

$ ./redis-trib.rb check 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: 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:7000 slots:0-5959,10922-11422 (6461 slots) master M: 393c6df5eb4b4cec323f0e4ca961c8b256e3460a 127.0.0.1:7002 slots:11423-16383 (4961 slots) master S: 3375be2ccc321932e8853234ffa87ee9fde973ff 127.0.0.1:7005 slots: (0 slots) slave M: e68e52cee0550f558b03b342f2f0354d2b8a083b 127.0.0.1:7001 slots:5960-10921 (4962 slots) master S: 48b728dbcedff6bf056231eb44990b7d1c35c3e0 127.0.0.1:7003 slots: (0 slots) slave S: 345ede084ac784a5c030a0387f8aaa9edfc59af3 127.0.0.1:7004 slots: (0 slots) slave [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.

根據(jù)檢查結(jié)果顯示, 集群運(yùn)作正常。

需要注意的就是, 在三個(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è)哈希槽, 因?yàn)楹髢烧叨紝⒆约旱?500?個(gè)哈希槽移動(dòng)到了節(jié)點(diǎn)?127.0.0.1:7000?。

一個(gè)更有趣的示例應(yīng)用

我們?cè)谇懊媸褂玫氖纠绦?example.rb?并不是十分有趣, 因?yàn)樗皇遣粩嗟貙?duì)集群進(jìn)行寫入, 但并不檢查寫入結(jié)果是否正確。 比如說, 集群可能會(huì)錯(cuò)誤地將?example.rb?發(fā)送的所有?SET?命令都改成了?SET?foo?42?, 但因?yàn)?example.rb?并不檢查寫入后的值, 所以它不會(huì)意識(shí)到集群實(shí)際上寫入的值是錯(cuò)誤的。

因?yàn)檫@個(gè)原因,?redis-rb-cluster 項(xiàng)目包含了一個(gè)名為?consistency-test.rb?的示例應(yīng)用, 這個(gè)應(yīng)用比起?example.rb?有趣得多: 它創(chuàng)建了多個(gè)計(jì)數(shù)器(默認(rèn)為?1000?個(gè)), 并通過發(fā)送?INCR?命令來增加這些計(jì)數(shù)器的值。

在增加計(jì)數(shù)器值的同時(shí),?consistency-test.rb?還執(zhí)行以下操作:

  • 每次使用?INCR?命令更新一個(gè)計(jì)數(shù)器時(shí), 應(yīng)用會(huì)記錄下計(jì)數(shù)器執(zhí)行?INCR?命令之后應(yīng)該有的值。 舉個(gè)例子, 如果計(jì)數(shù)器的起始值為?0?, 而這次是程序第?50?次向它發(fā)送?INCR?命令, 那么計(jì)數(shù)器的值應(yīng)該是?50?。
  • 在每次發(fā)送?INCR?命令之前, 程序會(huì)隨機(jī)從集群中讀取一個(gè)計(jì)數(shù)器的值, 并將它與自己記錄的值進(jìn)行對(duì)比, 看兩個(gè)值是否相同。

換句話說, 這個(gè)程序是一個(gè)一致性檢查器(consistency checker): 如果集群在執(zhí)行?INCR?命令的過程中, 丟失了某條?INCR?命令, 又或者多執(zhí)行了某條客戶端沒有確認(rèn)到的?INCR?命令, 那么檢查器將察覺到這一點(diǎn) —— 在前一種情況中,?consistency-test.rb?記錄的計(jì)數(shù)器值將比集群記錄的計(jì)數(shù)器值要大; 而在后一種情況中,?consistency-test.rb?記錄的計(jì)數(shù)器值將比集群記錄的計(jì)數(shù)器值要小。

運(yùn)行?consistency-test?程序?qū)a(chǎn)生類似以下的輸出:

$ ruby consistency-test.rb 925 R (0 err) | 925 W (0 err) | 5030 R (0 err) | 5030 W (0 err) | 9261 R (0 err) | 9261 W (0 err) | 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) |

每行輸出都打印了程序執(zhí)行的讀取次數(shù)和寫入次數(shù), 以及執(zhí)行操作的過程中因?yàn)榧翰豢捎枚a(chǎn)生的錯(cuò)誤數(shù)。

如果程序察覺了不一致的情況出現(xiàn), 它將在輸出行的末尾顯式不一致的詳細(xì)情況。

比如說, 如果我們?cè)?consistency-test.rb?運(yùn)行的過程中, 手動(dòng)修改某個(gè)計(jì)數(shù)器的值:

$ redis 127.0.0.1:7000> set key_217 0 OK

那么?consistency-test.rb?將向我們報(bào)告不一致情況:

(in the other tab I see...)94774 R (0 err) | 94774 W (0 err) | 98821 R (0 err) | 98821 W (0 err) | 102886 R (0 err) | 102886 W (0 err) | 114 lost | 107046 R (0 err) | 107046 W (0 err) | 114 lost |

在我們修改計(jì)數(shù)器值的時(shí)候, 計(jì)數(shù)器的正確值是?114?(執(zhí)行了?114?次?INCR?命令), 因?yàn)槲覀儗⒂?jì)數(shù)器的值設(shè)成了?0?, 所以?consistency-test.rb?會(huì)向我們報(bào)告說丟失了?114?個(gè)?INCR?命令。

因?yàn)檫@個(gè)示例程序具有一致性檢查功能, 所以我們用它來測(cè)試 Redis 集群的故障轉(zhuǎn)移操作。

故障轉(zhuǎn)移測(cè)試

在執(zhí)行本節(jié)操作的過程中, 請(qǐng)一直運(yùn)行?consistency-test?程序。

要觸發(fā)一次故障轉(zhuǎn)移, 最簡(jiǎn)單的辦法就是令集群中的某個(gè)主節(jié)點(diǎn)進(jìn)入下線狀態(tài)。

首先用以下命令列出集群中的所有主節(jié)點(diǎn):

$ redis-cli -p 7000 cluster nodes | grep master 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385482984082 0 connected 5960-10921 2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 master - 0 1385482983582 0 connected 11423-16383 97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master - 0 0 0 connected 0-5959 10922-11422

通過命令輸出, 我們知道端口號(hào)為?7000?、?7001?和?7002?的節(jié)點(diǎn)都是主節(jié)點(diǎn), 然后我們可以通過向端口號(hào)為?7002?的主節(jié)點(diǎn)發(fā)送?DEBUG SEGFAULT?命令, 讓這個(gè)主節(jié)點(diǎn)崩潰:

$ redis-cli -p 7002 debug segfault Error: Server closed the connection

現(xiàn)在, 切換到運(yùn)行著?consistency-test?的標(biāo)簽頁, 可以看到,?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) | 33749 R (578 err) | 33750 W (577 err) | 37918 R (578 err) | 37919 W (577 err) | 42077 R (578 err) | 42078 W (577 err) |

從?consistency-test?的這段輸出可以看到, 集群在執(zhí)行故障轉(zhuǎn)移期間, 總共丟失了?578?個(gè)讀命令和?577?個(gè)寫命令, 但是并沒有產(chǎn)生任何數(shù)據(jù)不一致。

這聽上去可能有點(diǎn)奇怪, 因?yàn)樵诮坛痰拈_頭我們提到過, Redis 使用的是異步復(fù)制, 在執(zhí)行故障轉(zhuǎn)移期間, 集群可能會(huì)丟失寫命令。

但是在實(shí)際上, 丟失命令的情況并不常見, 因?yàn)?Redis 幾乎是同時(shí)執(zhí)行將命令回復(fù)發(fā)送給客戶端, 以及將命令復(fù)制給從節(jié)點(diǎn)這兩個(gè)操作, 所以實(shí)際上造成命令丟失的時(shí)間窗口是非常小的。

不過, 盡管出現(xiàn)的幾率不高, 但丟失命令的情況還是有可能會(huì)出現(xiàn)的, 所以我們對(duì) Redis 集群不能提供強(qiáng)一致性的這一描述仍然是正確的。

現(xiàn)在, 讓我們使用?cluster?nodes?命令, 查看集群在執(zhí)行故障轉(zhuǎn)移操作之后, 主從節(jié)點(diǎn)的布局情況:

$ redis-cli -p 7000 cluster nodes 3fc783611028b1707fd65345e763befb36454d73 127.0.0.1:7004 slave 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 0 1385503418521 0 connected a211e242fc6b22a9427fed61285e85892fa04e08 127.0.0.1:7003 slave 97a3a64667477371c4479320d683e4c8db5858b1 0 1385503419023 0 connected 97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master - 0 0 0 connected 0-5959 10922-11422 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7005 master - 0 1385503419023 3 connected 11423-16383 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385503417005 0 connected 5960-10921 2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385503418016 3 connected

我重啟了之前下線的?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?下線而變成主節(jié)點(diǎn)的。

cluster?nodes?命令的輸出有點(diǎn)兒復(fù)雜, 它的每一行都是由以下信息組成的:

  • 節(jié)點(diǎn) ID :例如?3fc783611028b1707fd65345e763befb36454d73?。
  • ip:port?:節(jié)點(diǎn)的 IP 地址和端口號(hào), 例如?127.0.0.1:7000?, 其中?:0?表示的是客戶端當(dāng)前連接的 IP 地址和端口號(hào)。
  • 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 就是?3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e?。
  • 集群最近一次向節(jié)點(diǎn)發(fā)送?PING?命令之后, 過去了多長(zhǎng)時(shí)間還沒接到回復(fù)。
  • 節(jié)點(diǎn)最近一次返回?PONG?回復(fù)的時(shí)間。
  • 節(jié)點(diǎn)的配置紀(jì)元(configuration epoch):詳細(xì)信息請(qǐng)參考?Redis 集群規(guī)范?。
  • 本節(jié)點(diǎn)的網(wǎng)絡(luò)連接情況:例如?connected?。
  • 節(jié)點(diǎn)目前包含的槽:例如?127.0.0.1:7001?目前包含號(hào)碼為?5960?至?10921?的哈希槽。

添加新節(jié)點(diǎn)到集群

根據(jù)新添加節(jié)點(diǎn)的種類, 我們需要用兩種方法來將新節(jié)點(diǎn)添加到集群里面:

  • 如果要添加的新節(jié)點(diǎn)是一個(gè)主節(jié)點(diǎn), 那么我們需要?jiǎng)?chuàng)建一個(gè)空節(jié)點(diǎn)(empty node), 然后將某些哈希桶移動(dòng)到這個(gè)空節(jié)點(diǎn)里面。
  • 另一方面, 如果要添加的新節(jié)點(diǎn)是一個(gè)從節(jié)點(diǎn), 那么我們需要將這個(gè)新節(jié)點(diǎn)設(shè)置為集群中某個(gè)節(jié)點(diǎn)的復(fù)制品(replica)。

本節(jié)將對(duì)以上兩種情況進(jìn)行介紹, 首先介紹主節(jié)點(diǎn)的添加方法, 然后再介紹從節(jié)點(diǎn)的添加方法。

無論添加的是那種節(jié)點(diǎn), 第一步要做的總是添加一個(gè)空節(jié)點(diǎn)。

我們可以繼續(xù)使用之前啟動(dòng)?127.0.0.1:7000?、?127.0.0.1:7001?等節(jié)點(diǎn)的方法, 創(chuàng)建一個(gè)端口號(hào)為?7006?的新節(jié)點(diǎn), 使用的配置文件也和之前一樣, 只是記得要將配置中的端口號(hào)改為?7000?。

以下是啟動(dòng)端口號(hào)為?7006?的新節(jié)點(diǎn)的詳細(xì)步驟:

  • 在終端里創(chuàng)建一個(gè)新的標(biāo)簽頁。
  • 進(jìn)入?cluster-test?文件夾。
  • 創(chuàng)建并進(jìn)入?7006?文件夾。
  • 將?redis.conf?文件復(fù)制到?7006?文件夾里面,然后將配置中的端口號(hào)選項(xiàng)改為?7006?。
  • 使用命令?../../redis-server?redis.conf?啟動(dòng)節(jié)點(diǎn)。
  • 如果一切正常, 那么節(jié)點(diǎn)應(yīng)該會(huì)正確地啟動(dòng)。

    接下來, 執(zhí)行以下命令, 將這個(gè)新節(jié)點(diǎn)添加到集群里面:

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

    命令中的?add-node?表示我們要讓?redis-trib?將一個(gè)節(jié)點(diǎn)添加到集群里面,?add-node?之后跟著的是新節(jié)點(diǎn)的 IP 地址和端口號(hào), 再之后跟著的是集群中任意一個(gè)已存在節(jié)點(diǎn)的 IP 地址和端口號(hào), 這里我們使用的是?127.0.0.1:7000?。

    通過?cluster?nodes?命令, 我們可以確認(rèn)新節(jié)點(diǎn)?127.0.0.1:7006?已經(jīng)被添加到集群里面了:

    redis 127.0.0.1:7006> cluster nodes 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385543178575 0 connected 5960-10921 3fc783611028b1707fd65345e763befb36454d73 127.0.0.1:7004 slave 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 0 1385543179583 0 connected f093c80dde814da99c5cf72a7dd01590792b783b :0 myself,master - 0 0 0 connected 2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385543178072 3 connected a211e242fc6b22a9427fed61285e85892fa04e08 127.0.0.1:7003 slave 97a3a64667477371c4479320d683e4c8db5858b1 0 1385543178575 0 connected 97a3a64667477371c4479320d683e4c8db5858b1 127.0.0.1:7000 master - 0 1385543179080 0 connected 0-5959 10922-11422 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7005 master - 0 1385543177568 3 connected 11423-16383

    新節(jié)點(diǎn)現(xiàn)在已經(jīng)連接上了集群, 成為集群的一份子, 并且可以對(duì)客戶端的命令請(qǐng)求進(jìn)行轉(zhuǎn)向了, 但是和其他主節(jié)點(diǎn)相比, 新節(jié)點(diǎn)還有兩點(diǎn)區(qū)別:

    • 新節(jié)點(diǎn)沒有包含任何數(shù)據(jù), 因?yàn)樗鼪]有包含任何哈希桶。
    • 盡管新節(jié)點(diǎn)沒有包含任何哈希桶, 但它仍然是一個(gè)主節(jié)點(diǎn), 所以在集群需要將某個(gè)從節(jié)點(diǎn)升級(jí)為新的主節(jié)點(diǎn)時(shí), 這個(gè)新節(jié)點(diǎn)不會(huì)被選中。

    接下來, 只要使用?redis-trib?程序, 將集群中的某些哈希桶移動(dòng)到新節(jié)點(diǎn)里面, 新節(jié)點(diǎn)就會(huì)成為真正的主節(jié)點(diǎn)了。

    因?yàn)槭褂?redis-trib?移動(dòng)哈希桶的方法在前面已經(jīng)介紹過, 所以這里就不再重復(fù)介紹了。

    現(xiàn)在, 讓我們來看看, 將一個(gè)新節(jié)點(diǎn)轉(zhuǎn)變?yōu)槟硞€(gè)主節(jié)點(diǎn)的復(fù)制品(也即是從節(jié)點(diǎn))的方法。

    舉個(gè)例子, 如果我們打算讓新節(jié)點(diǎn)成為?127.0.0.1:7005?的從節(jié)點(diǎn), 那么我們只要用客戶端連接上新節(jié)點(diǎn), 然后執(zhí)行以下命令就可以了:

    redis 127.0.0.1:7006> cluster replicate 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e

    其中命令提供的?3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e?就是主節(jié)點(diǎn)?127.0.0.1:7005?的節(jié)點(diǎn) ID 。

    執(zhí)行?cluster?replicate?命令之后, 我們可以使用以下命令來確認(rèn)?127.0.0.1:7006?已經(jīng)成為了 ID 為?3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e?的節(jié)點(diǎn)的從節(jié)點(diǎn):

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

    3c3a0c...?現(xiàn)在有兩個(gè)從節(jié)點(diǎn), 一個(gè)從節(jié)點(diǎn)的端口號(hào)為?7002?, 而另一個(gè)從節(jié)點(diǎn)的端口號(hào)為?7006?。

    移除一個(gè)節(jié)點(diǎn)

    未完待續(xù)。

    from:?http://redisdoc.com/topic/cluster-tutorial.html

    總結(jié)

    以上是生活随笔為你收集整理的Redis集群教程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。