redis集羣搭建及分析

概述

redis提供了無中心化的模式來提供對key的shading, 提供數據存儲的master節點與master節點之間是對等的, master節點與master節點之間經過gossip協議進行通訊,以實現集羣選主,失效轉移, 觸發數據遷移等操做.node

1. redis 集羣搭建

1.1 配置項說明

cluster-enabled <yes/no>: 是否開啓集羣模式, yes開啓, no不開啓.
cluster-config-file <filename>: 集羣配置文件,用於集羣信息,用戶不能編輯或改變該文件.
cluster-node-timeout <milliseconds>: 檢測集羣中master節點失敗最大時間,當master節點超過該時間還沒法聯繫時, 若是有備份節點則備份節點將對maser節點進行失效轉移,若干沒有則表示該master節點失效, 當集羣中大多數master節點失效時,集羣將再也不提供操做.
cluster-slave-validity-factor <factor>:master節點檢測到超時時最大鏈接重試次數, 默認爲0, 即一旦檢測到超時則slave節點就對master進行失效轉移, 當該值爲正數時, 在factor*timeout的時間週期內, slave不會對master進行失效轉移.
cluster-migration-barrier <count>: master節點保存鏈接的最小slave節點數.
cluster-require-full-coverage <yes/no>:當主節點失效時是否繼續提供服務, 默認yes, 即主節點失效時將不提供服務, no, 失效時仍然提供服務.git

1.2 集羣搭建

下面將搭建3主3從的集羣, 主節點端口分別爲7000, 7001, 70002, 從節點端口爲7003, 7004, 7005.即一個master節點對應一個slave節點.
建立配置文件以下:github

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

建立6個文件夾, 文件夾名爲端口名, 並將配置文件拷貝到各文件夾,端口修改成對應端redis

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

將redis-server執行程序拷貝到各文件夾,並啓動緩存

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

運行後結果以下:服務器

14073:M 11 Aug 14:45:40.198 * No cluster configuration found, I'm 5714dd95e99999f7130eba44747f7a15aa8f5394

5714dd95e99999f7130eba44747f7a15aa8f5394, 表示節點Id.app

建立集羣:
完成以上步驟後,各節點獨立運行, 並無造成集羣, 下面須要相互之間通訊,組成集羣, 這裏使用redis自帶的工具redis-trib,
首先安裝 redis gem運維

gem install redis

建立集羣工具

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

建立成功性能

[OK] All 16384 slots covered

查看集羣狀態:

127.0.0.1:7002> cluster nodes
4406983653bd90043b5b7f65af0afc571bb2d93c 127.0.0.1:7002 myself,master - 0 0 3 connected 10923-16383
fd5e7a729072b0e7e29ff5a4935a0151c470a47d 127.0.0.1:7005 slave 4406983653bd90043b5b7f65af0afc571bb2d93c 0 1470899978447 3 connected
5714dd95e99999f7130eba44747f7a15aa8f5394 127.0.0.1:7000 master - 0 1470899976944 1 connected 0-5460
aca053afafd21f887d3bc9d87c16597f67b7e513 127.0.0.1:7001 master - 0 1470899977946 2 connected 5461-10922
c450ae75e23a2cfeda901c0de77ef0cae85a8a8b 127.0.0.1:7003 slave 5714dd95e99999f7130eba44747f7a15aa8f5394 0 1470899978947 1 connected
576764adacf6737b5ef6e63ff5ea2cb3a9aae43d 127.0.0.1:7004 slave aca053afafd21f887d3bc9d87c16597f67b7e513 0 1470899977445 5 connected

命令測試:

./redis-cli -c -p 7000
127.0.0.1:7000> set foo bar
-> Redirected to slot [12182] located at 127.0.0.1:7002
OK
127.0.0.1:7002> set hello world
-> Redirected to slot [866] located at 127.0.0.1:7000
OK
127.0.0.1:7000>
127.0.0.1:7000> get hello
"world"
127.0.0.1:7000> get foo
-> Redirected to slot [12182] located at 127.0.0.1:7002
"bar"

集羣搭建成功

2. slots映射說明

redis 內部提供 16384個槽,每一個節點分配固定槽數, 也就是說一個集羣最多支持16348個節點, 若有A, B, C三個節點, 則分配以下:

Node A  [0,5500]
    Node B [5501,11000]
    Node C [11001,16383]

對於一個key, 首先對其作crc16, 並將結果對16384去模, 所得的結果則表示key所屬的槽, 經過查詢槽的分配策略, 獲得key分配的服務器, 從而實現key在集羣內部shading.

3. 重定向命令

moved重定向命令:
client端與redis集羣的任一節點創建鏈接後, 對key進行操做時:
若是收到命令的redis節點發現key對應的槽不屬於本身處理,則會給client回覆moved錯誤, 並返回槽所在的真正節點,
client端收到moved錯誤後,重定向到指定節點作操做,
這裏能夠能夠看出, 任何一個redis節點均保存了集羣中的其餘節點槽對應信息.另外爲了提升client性能, client會緩存槽與服務器的對應信息, 因此收到moved從定向時, 會相應的更新緩存.

ask重定向命令:
ask重定向發送在集羣中正在對槽對應的key進行數據遷移時,具體流程爲:
當client端向節點nodeA發送key1的處理命令時, 若果A節點具備key1對應的槽slot1的處理權, 且key1沒法在nodeA查詢到, 且slot1正處於遷移狀態,則nodeA返回ask重定向命令, 將其指向遷移的目標節點nodeB
client收到重定向命令後, 向nodeB先發送asking命令, 再發送key1的處理命令.
nodeB接收到asking命令後, 將對收到後續一個命令作特殊處理,也就是即便發現slot1不屬於nodeB處理,仍然會執行key1的處理命令.ask從定向命令不會引發client端更新緩存,且nodeB只處理一次.

4. 失效轉移

redis集羣有實行主備機制, slave節點保存着master節點全部數據備份, 當master節點失效時,slave節點會對master節點進行失效轉移.具體流程爲:
集羣中master節點之間按期會進行通訊, 當集羣中對等的masterA節點發現某個節點masterB超時無迴應時, 則將該masterB節點置爲faling,並廣播檢測到的狀況.
同 時masterA會記錄集羣中其餘master節點對masterB的檢測結果, 若是發現集羣中大部分(n/2+1)的master節點均認爲該節點faling,則將masterB的裝置爲failed, 即失效,同時, masterA向masterB的slave節點發送命令讓其選舉.
選舉時在一個時間紀元內會存在兩種狀況, 要麼一個slave節點得到大於等於n/2+1的投票成爲新的master, 要麼超時.
選擇成功後的slave將會成爲master節點,繼續工做,而超時則進入新一輪選舉,直到選出新的master.
這裏具備投票權的master只能投票一次,從而保證只有一個master能當選.而失效的master節點又從新上線後將轉爲slave節點.

redis集羣的測試結果以下:
在上面搭建的集羣中7004爲7001的slave節點,現將7001掛掉, 查看集羣狀態:

127.0.0.1:7002> cluster nodes
4406983653bd90043b5b7f65af0afc571bb2d93c 127.0.0.1:7002 myself,master - 0 0 3 connected 10923-16383
fd5e7a729072b0e7e29ff5a4935a0151c470a47d 127.0.0.1:7005 slave 4406983653bd90043b5b7f65af0afc571bb2d93c 0 1470903542509 3 connected
5714dd95e99999f7130eba44747f7a15aa8f5394 127.0.0.1:7000 master - 0 1470903542509 1 connected 0-5460
aca053afafd21f887d3bc9d87c16597f67b7e513 127.0.0.1:7001 master,fail - 1470903522089 1470903520389 2 disconnected
c450ae75e23a2cfeda901c0de77ef0cae85a8a8b 127.0.0.1:7003 slave 5714dd95e99999f7130eba44747f7a15aa8f5394 0 1470903541506 1 connected
576764adacf6737b5ef6e63ff5ea2cb3a9aae43d 127.0.0.1:7004 master - 0 1470903543513 7 connected 5461-10922

能夠看到7001已經失效, 同時7004成了新的master節點.

如今又將7001重啓, 查看集羣狀態:

127.0.0.1:7002> cluster nodes
4406983653bd90043b5b7f65af0afc571bb2d93c 127.0.0.1:7002 myself,master - 0 0 3 connected 10923-16383
fd5e7a729072b0e7e29ff5a4935a0151c470a47d 127.0.0.1:7005 slave 4406983653bd90043b5b7f65af0afc571bb2d93c 0 1470903594126 3 connected
5714dd95e99999f7130eba44747f7a15aa8f5394 127.0.0.1:7000 master - 0 1470903596130 1 connected 0-5460
aca053afafd21f887d3bc9d87c16597f67b7e513 127.0.0.1:7001 slave 576764adacf6737b5ef6e63ff5ea2cb3a9aae43d 0 1470903594727 7 connected
c450ae75e23a2cfeda901c0de77ef0cae85a8a8b 127.0.0.1:7003 slave 5714dd95e99999f7130eba44747f7a15aa8f5394 0 1470903595730 1 connected
576764adacf6737b5ef6e63ff5ea2cb3a9aae43d 127.0.0.1:7004 master - 0 1470903595629 7 connected 5461-10922

7001 成爲了slave節點.

5. 集羣擴展

集羣擴展分爲兩個方面,分別爲新增節點(包括新增master節點, 新增slave節點), 及減小節點.
新增master節點
流程和前面搭建集羣時一致, 先給節點分配一個端口並運行,如7006.而後經過redis-trib執行如下命令

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

如上, 第一個地址爲新增的地址, 第二個地址爲集羣中已經運行的master地址,執行完以上命令後master雖然加入了集羣,可是它並無分配到槽進行數據處理
這是須要進行reshaing, 命令以下:

./redis-trib.rb reshard --from <node-id> --to <node-id> --slots <number of slots> --yes <host>:<port>

新增slave節點

./redis-trib.rb add-node --slave --master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7006 127.0.0.1:7000

其中,master-id表示要成爲誰的slave.

減小節點

./redis-trib del-node 127.0.0.1:7000 `<node-id>`

6. 總結

從 整個流程來看,.無論仍是集羣的建立仍是 後期集羣的運維,redis都很是的順暢,這無疑提升了使用的門檻,就以當前redis的性能來講,作redis緩存集羣是個不錯的選擇,不過,若是要在 運營環境進行使用,仍是須要更加方便的部署及運維工具,這裏推薦搜狐的開源工具cachecloud, 的確十分好用,git地址見:
https://github.com/sohutv/cac...

相關文章
相關標籤/搜索