水平有限,如果您在閱讀過程中發現有翻譯的不合理的地方,請留言,我會盡快修改,謝謝。
使用create-cluster角本創建Redis集群
如果你不想通過配置來創建Redis集群並且不想向上邊闡明的一樣手動的去執行單獨的實例,這里還有更簡單的系統(但是你將不會學到等量的操作細節)
只需查看在Redis發行版本中的utils/create-cluster目錄。在里面有一個叫 create-cluster的角本(和包含他的目錄名稱一樣),為了啟動包含3個主節點和3個從節點的6節點集群,只需輸入下面的命令:
1.create-cluster start
2.create-cluster create
在第2步當redis-trib實用工具程序想讓你接受集群的布局時答復為yes.
現在你可以和你的集群進行交互了,第一個節點將默認使用30001端口啟動。當你操作完后,使用下面的命令停止集群:
1.create-cluster stop
請閱讀此目錄內的README文件,以獲得有關如何運行角本的更多信息。
和集群玩耍
在這個階段Redis集群有一個問題是缺少客戶端庫實現。
下面是我知道的實現:
>
redis-rb-cluster是我(@antirez)用Ruby實現的,做為其它語言的參考。這是圍繞原始的redis-rb的簡單包裝,高效實現了和集群通信的最小語義。
>
redis-py-clusterredis-rb-cluster的Python移植版本,支持redis-py的絕大部分功能。還處於積極開發中。
> 流行的
Predis現在也支持Redis集群,該支持最近剛更新過,並且還在積極開發中。
> 使用最多的java客戶端,
Jedis最近新增了對Redis集群的支持,在項目README里查看
Jedis Cluster 章節。
>
StackExchange.Redis 提供對C#的支持(並且適用於大多數.NET語言; VB, F#等)
>
redis-go-cluster 提供對Node.js和io.js的支持,它是基於thunk/promise的redis客戶端並含有管道和集群。
>
redis-go-cluster是使用
Redigo library client做為基本客戶端的Go語言的Redis集群實現,通過結果聚合實現MGET/MSET。
> 在GitHub上Redis unstable分支內的redis-cli實用工具在使用-c開關啟動時實現了最基本的集群支持。
測試Redis集群 最簡單的方式是嘗試使用上述任意一種客戶端,或者只是redis-cli命令行工具。
下面是使用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"
注意:如果你使用角本創建的集群,你的節點可能監聽不同的端口,默認情況下從30001開始。
redis-cli對集群的支持是非常基本的,所以他總是使用Redis集群節點將客戶端重定向一個到正確節點。一個完善的客戶端可以做的更好,並且緩存hash槽和節點地址的映射,用於直接使用正確的連接到正確的節點。這個映射只有在集群配置有變動時才會被刷新,例如故障轉移之后或者系統管理員通過地址修改集群層或移除節點之后。
編寫一個redis-rb-cluster實例程序
在展示如何操作redis集群,像這些執行故障轉移,或者重新分片(resharding)之前, 我們需要創建一些示例程序,至少能明白簡單的Redis集群客戶端交互語義。
這樣我們可以運行一個示例同時嘗試讓節點發生故障,或者開始重新分片(resharding),以了解在真實環境中Redis集群的行為。這對於了解當集群沒有寫入命令時發生了什么不是非常有幫助。
本節使用兩個示例來解釋redis-rb-cluster的基本用法。下面是第一個,它是redis-rb-cluster發行版本內的example.rb文件。
1 require './cluster' 2 3 if ARGV.length != 2 4 startup_nodes = [ 5 {:host => "127.0.0.1", :port => 7000}, 6 {:host => "127.0.0.1", :port => 7001} 7 ] 8 else 9 startup_nodes = [ 10 {:host => ARGV[0], :port => ARGV[1].to_i} 11 ] 12 end 13 14 rc = RedisCluster.new(startup_nodes,32,:timeout => 0.1) 15 16 last = false 17 18 while not last 19 begin 20 last = rc.get("__last__") 21 last = 0 if !last 22 rescue => e 23 puts "error #{e.to_s}" 24 sleep 1 25 end 26 end 27 28 ((last.to_i+1)..1000000000).each{|x| 29 begin 30 rc.set("foo#{x}",x) 31 puts rc.get("foo#{x}") 32 rc.set("__last__",x) 33 rescue => e 34 puts "error #{e.to_s}" 35 end 36 sleep 0.1 37 }
這個程序做了非常簡單的事情,他以foo<number>的形式,一個接一個的設置鍵值為number,所以如果你運行這個程序它的結果是下面的命令流:
- SET foo0 0
- SET foo1 1
- SET foo2 2
- And so forth...
這個程序看起來比通常應用更復雜,因為他被設計為在屏幕上顯示錯誤信息,而不是發生異常退出,所以每一個與集群執行的操作都被包在begin recue塊中。
在程序中第14行代碼是第一處有意思的地方,他創建了Redis集群對象,使用啟動節點(startup nodes )列表作為參數,允許連接這個對象對應不同節點的最大數量,最后在給定的操作超后被認為故障 。
啟動節點不需要集群內的所有節點。重要的是至少有一個節點是可訪問的。注意只要redis-rb-cluster能連接到一個節點就會更新啟動列表。你應該期待其他嚴格的客戶端也有這樣的行為。
現在我們已經有Redis集群對象的實例保存在
rc變量中,我們准備好象使用一般的redis對象實例一樣使用這個對象。
這是確實發生在
18 到 26行:當我們重啟個這示例,面不想重新從foo0開始,所以我們把這個計數保存在Redis內。上面的代碼被設計為讀取這個計數器,或者如果這個計數器不存在,就設置為0.
然而注意他是一個怎樣的while循環,由於我們想一次又一次的嘗試,即使集群已關閉並且返回錯誤。不般的應用程序不需要這么小心。
28到37行開始主要的的循環,循環里設置鍵值或者顯示錯誤信息。
注意在循環的最后調用了sleep。在你的測試中如果你想寫入到集群的速度足夠快那就把sleep去掉(相對於快這里只是一個頻繁的循環,當然不是真正的並發,這樣在最好的狀態下,你通常會得到10k ops/s)。
一般情況下對於示例程序能容易的被人類跟隨會把寫入速度放慢。
開始這個應用程序后就產生下面的輸出:
ruby ./example.rb 1 2 3 4 5 6 7 8 9 ^C (I stopped the program here)
這不是一個非常有趣的程序,我們一會兒會使用一個更好的,但是我們已經可以看到在程序運行起來后在分片期間發生了什么。
集群的重新分片(Resharding)
現在我們准備嘗試集群的重新分片。為此需要example.rb程序保持運行,因此可以看到是否對程序運行過程中有影響。同樣的在分片期間為了更嚴格的寫入負載你可能可能想注釋掉sleep調用。
重新分片基本上意味着把哈希槽 從一組節點移動到另一組節點,就像使用redis-trib實用工具完成集群的創建一樣。
只需輸入下面的代碼就可以開始重新分片:
./redis-trib.rb reshard 127.0.0.1:7000
你唯一需要做的就是指定一個節點,redis-trib會自動的找到其他的節點。
一般情況下需要管理員的支持reids-trib才能重新分片,你不能說只從這個節點移動槽的5%到其它節點(但是這是很空間實現的)。所以從詢問開始。第一是你想要做多大的分片:
How many slots do you want to move (from 1 to 16384)?
我們可以嘗試對1000個哈希槽分片,如果示例依然在不調用sleep的情況下運行,那么它已經包含了一些重要的鍵。
這時,redis-trib需要知道分片的目標什么是 。也就是說將要接收哈希槽的節點。我將使用第一個主節點,也就是127.0.0.1:7000,但是我需要指定實例的節點ID。通過redis-trib已經在一個列表內打印出來了,但是如果需要我經常使用下面的命令來找節點的ID:
$ redis-cli -p 7000 cluster nodes | grep myself 97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master - 0 0 0 connected 0-5460
ok所以我們的目標節點是 97a3a64667477371c4479320d683e4c8db5858b1.
現在你會得到一個詢問你想從哪些節點來取這些鍵,為了能從其它所有的主節點取出一些哈希槽我只需輸入all.
在最后的配置后,你會看到每一個redis-trib要從一個節點移動到另一個節點的槽的信息,並且會為每一個從一個節點移動到另一個節點的實際的鍵打印一個點。
在分片過程中你會看到對你運行中的示例是沒有影響的。在分片期間,只要你想,你可以多次停止或重啟你的示例程序 。
分片結束后,你可以使用下面的命令來測試集群的健康:
通常將覆蓋所有的槽,但這些主節點127.0.0.1:7000 將有更多的哈希槽,大約為6461.