Redis(4.0及以下版本)cluster集群原理及搭建

Redis cluster集群:原理及搭建


原文:

https://blog.csdn.net/truelove12358/article/details/79612954

Redis(4.0及以下版本)cluster集群原理及搭建

redis

1.為什麼使用redis?

redis是一種典型的no-sql 即非關係數據庫 像python的字典一樣 存儲key-value鍵值對工作在memory中

所以很適合用來充當整個互聯網架構中各級之間的cache 比如lvs的4層轉發層 nginx的7層代理層

尤其是lnmp架構應用層如php-fpm或者是Tomcat到mysql之間 做一個cache 以減輕db的壓力

因為有相當一部分的數據 只是簡單的key-value對應關係,而且在實際的業務中常常在短時間內迅速變動

如果用關係數據庫mysql之類存儲 會大大增加對db的訪問 導致db的負擔很重 因為所有的require中的大部分最後都要匯聚到db

所以如果想要業務穩定 那麼解決db的壓力 就是關鍵 所以現在大部分的解決方案就是在db層之上的各級使用多級的no-sql

像memcache redis 等 來為db提供緩衝

2.為什麼使用redis-cluster?

為了在大流量訪問下提供穩定的業務,集群化是存儲的必然形態

未來的發展趨勢肯定是雲計算和大數據的緊密結合 只有分佈式架構能滿足要求

如果沒有集群化 何來的分佈式?

3.順帶一提總結一波今天的redis原理之數據持久化

雖然redis這種no-sql一般都是作為cache來服務 但是如果完全沒有數據可持久化的方法 那麼顯得有些單薄

就像memcache 由於這種no-sql是工作在memory的 那麼由於memory的實體是ram

所以如果重啟或者宕機 memory中的數據就全沒了 數據的一致性的不到保障

但是 redis不同 redis有相對的數據持久化的方案 由兩種方式構成 aof & rdb

aof就像關係數據庫中的binlog一樣 把每一次寫操作以追加的形式記錄在其中以文件的形式刷到磁盤裡

並且可以使用不同的fsync策略 無fsync,每秒fsync,每次寫的時候fsync.

使用默認的每秒fsync策略,Redis的性能依然很好(fsync是由後臺線程進行處理的,主線程會盡力處理客戶端請求)

一旦出現故障,最多丟失1秒的數據.

但是缺點也隨之而來 那就是aof文件的大小會隨著時間線性增長 一段時間之後 就會變得很大

如果要在一端以AOF的形式來恢復數據 那麼由於AOF文件的巨大體積 可能會讓進程如同假死一樣 十分的慢

rdb則是一種快照機制

redis工作在內存中 rdb就是每隔一段時間 對內存中的數據做一次快照 保存在rdb文件中

而且redis的主從同步可以實現異步 也是由於rdb的機制 他在做快照時會fork出一個子進程 由子進程來做快照

父進程完全處理請求 毫不影響 很適合數據的備份

但是問題是 如果數據量很大的話 rdb它要保存一個完整的數據集 是一個大的工作 如果時間間隔設置的太短

那麼嚴重影響redis的性能 但是按照常規設置的話 如5分鐘一次 那麼如果宕機或者重啟 就會基於上次做rdb的時間

從而丟失分鐘級的數據

point:在redis4.0的新特性中 採用了aof-rdb的混合方案來保障數據的持久性 但是官方的說法是還不成熟

是一個長期的工作 所以有待觀察吧

4.redis集群實現方案:

關於redis的集群化方案 目前有三種

(1)Twitter開發的twemproxy

(2)豌豆莢開發的codis

(3)redis官方的redis-cluster

簡介:twemproxy架構簡單 就是用proxy對後端redis server進行代理 但是由於代理層的消耗性能很低 而且通常涉及多個key的操作都是不支持的 而且本身不支持動態擴容和透明的數據遷移 而且也失去維護 Twitter內部已經不使用了

redis-cluster是三個裡性能最強大的 因為他使用去中心化的思想 使用hash slot方式 將16348個hash slot 覆蓋到所有節點上 對於存儲的每個key值 使用CRC16(KEY)&16348=slot 得到他對應的hash slot 並在訪問key時就去找他的hash slot在哪一個節點上 然後由當前訪問節點從實際被分配了這個hash slot的節點去取數據 節點之間使用輕量協議通信 減少帶寬佔用 性能很高 自動實現負載均衡與高可用 自動實現failover 並且支持動態擴展 官方已經玩到可以1000個節點 實現的複雜度低 總之個人比較喜歡這個架構 因為他的去中心化思想免去了proxy的消耗 是全新的思路

但是它也有一些不足 例如官方沒有提供圖形化管理工具 運維體驗差 全手工數據遷移 並且自己對自己本身的redis命令支持也不完全等 但是這些問題 我覺得不能掩蓋他關鍵的新思想所帶來的的優勢 隨著官方的推進 這些問題應該都能在一定時間內得到解決 那麼這時候去中心化思想帶來的高性能就會表現出他巨大的優勢

codis使用的也是proxy思路 但是做的比較好 是這兩種之間的一箇中間級 而且支持redis命令是最多的 有圖形化GUI管理和監控工具 運維友好 這個過段時間會詳細另外寫出來原理 工作機制和搭建實現

Redis集群

基本介紹 Redis 集群是一個可以在多個 Redis 節點之間進行數據共享的設施installation。

Redis 集群不支持那些需要同時處理多個鍵的 Redis 命令, 因為執行這些命令需要在多個 Redis 節點之間移動數據, 並且在高負載的情況下, 這些命令將降低Redis集群的性能, 並導致不可預測的行為。

Redis 集群通過分區partition來提供一定程度的可用性availability: 即使集群中有一部分節點失效或者無法進行通訊, 集群也可以繼續處理命令請求。

Redis集群提供了以下兩個好處:

將數據自動切分split到多個節點的能力。 當集群中的一部分節點失效或者無法進行通訊時, 仍然可以繼續處理命令請求的能力。 集群原理 redis-cluster架構圖 redis-cluster架構圖

所有的redis節點彼此互聯(PING-PONG機制),內部使用二進制協議優化傳輸速度和帶寬。

節點的fail是通過集群中超過半數的節點檢測失效時才生效。

客戶端與redis節點直連,不需要中間proxy層.客戶端不需要連接集群所有節點,連接集群中任何一個可用節點即可。

redis-cluster把所有的物理節點映射到[0-16383]slot上,cluster 負責維護nodeslotvalue

Redis集群中內置了 16384 個哈希槽,當需要在 Redis 集群中放置一個 key-value 時,redis 先對key 使用 crc16 算法算出一個結果,然後把結果對 16384 求餘數,這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,redis 會根據節點數量大致均等的將哈希槽映射到不同的節點

redis-cluster投票:容錯 redis-cluster投票:容錯

投票過程是集群中所有master參與,如果半數以上master節點與master節點通信超時(cluster-node-timeout),認為當前master節點掛掉.

什麼時候整個集群不可用(cluster_state:fail)?

如果集群任意master掛掉,且當前master沒有slave.集群進入fail狀態,也可以理解成集群的slot映射[0-16383]不完整時進入fail狀態. redis-3.0.0.rc1加入cluster-require-full-coverage參數,默認關閉,打開集群兼容部分失敗. 如果集群超過半數以上master掛掉,無論是否有slave,集群進入fail狀態. Redis集群搭建 Redis單機版的安裝見博客《redis入門——安裝篇》,安裝好之後,將redis複製成6份,注意要將.rdb和.aof後綴的文件刪除,如果有的話。

Ruby環境 使用

yum -y install ruby
yum -y install rubygems

安裝ruby環境。 網上下載redis-3.0.0.gem,執行gem install redis-3.0.0.gem安裝。

redis配置文件修改 現在已經準備好了,6份乾淨的redis,如下所示

[root@localhost redis-cluster]# pwd
/usr/local/redis/redis-cluster
[root@localhost redis-cluster]# ll
total 72
drwxr-xr-x 2 root root 4096 Nov 2 00:17 redis1
drwxr-xr-x 2 root root 4096 Nov 2 00:25 redis2
drwxr-xr-x 2 root root 4096 Nov 2 00:25 redis3
drwxr-xr-x 2 root root 4096 Nov 2 00:25 redis4
drwxr-xr-x 2 root root 4096 Nov 2 00:25 redis5
drwxr-xr-x 2 root root 4096 Nov 2 00:25 redis6
-rwxr-xr-x 1 root root 48141 Nov 2 00:16 redis-trib.rb
[root@localhost redis-cluster]#

PS:注意,這裡已經將redis源文件src目錄下的redis-trib.rb文件拷貝過來了。 redis-trib.rb這個文件是redis集群的管理文件,ruby腳本。

將六個節點的redis.conf配置文件按照如下進行修改

################################ GENERAL #####################################

# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
daemonize yes

# Accept connections on the specified port, default is 6379.
# If port 0 is specified Redis will not listen on a TCP socket.
port *

################################ REDIS CLUSTER ###############################

#
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# WARNING EXPERIMENTAL: Redis Cluster is considered to be stable code, however
# in order to mark it as "mature" we need to wait for a non trivial percentage
# of users to deploy it in production.
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#
# Normal Redis instances can't be part of a Redis Cluster; only nodes that are
# started as cluster nodes can. In order to start a Redis instance as a
# cluster node enable the cluster support uncommenting the following:
#
cluster-enabled yes

PS:端口號如果是同一臺主機的話,必須不同。不同主機可以相同。

PS:我這裡是使用一臺主機,所以我將六個節點的端口號修改為7001-7006

編寫集群啟動腳本和停止腳本 啟動腳本start-all.sh

cd redis1
./redis-server redis.conf
cd ..
cd redis2
./redis-server redis.conf
cd ..
cd redis3
./redis-server redis.conf
cd ..
cd redis4
./redis-server redis.conf
cd ..
cd redis5
./redis-server redis.conf
cd ..
cd redis6
./redis-server redis.conf
cd ..

停止腳本stop-all.sh

./redis1/redis-cli -p 7001 shutdown 

./redis1/redis-cli -p 7002 shutdown
./redis1/redis-cli -p 7003 shutdown
./redis1/redis-cli -p 7004 shutdown
./redis1/redis-cli -p 7005 shutdown
./redis1/redis-cli -p 7006 shutdown

PS:兩個腳本都放在如下所屬目錄

[root@localhost redis-cluster]# pwd
/usr/local/redis/redis-cluster
[root@localhost redis-cluster]# ll
total 80
drwxr-xr-x 2 root root 4096 Nov 2 00:52 redis1
drwxr-xr-x 2 root root 4096 Nov 2 00:51 redis2
drwxr-xr-x 2 root root 4096 Nov 2 00:53 redis3
drwxr-xr-x 2 root root 4096 Nov 2 00:53 redis4
drwxr-xr-x 2 root root 4096 Nov 2 00:53 redis5
drwxr-xr-x 2 root root 4096 Nov 2 00:53 redis6
-rwxr-xr-x 1 root root 48141 Nov 2 00:16 redis-trib.rb
-rw-r--r-- 1 root root 252 Nov 2 00:55 start-all.sh
-rw-r--r-- 1 root root 216 Nov 2 00:57 stop-all.sh
[root@localhost redis-cluster]#

修改權限

[root@localhost redis-cluster]# chmod -u+x start-all.sh stop-all.sh 
啟動節點
[root@localhost redis-cluster]# ./start-all.sh
[root@localhost redis-cluster]# ps aux | grep redis
root 2924 0.8 0.1 33932 2048 ? Ssl Nov01 3:53 ./redis-server *:6379 [cluster]
root 11924 0.0 0.1 33936 1948 ? Ssl 01:01 0:00 ./redis-server *:7001 [cluster]
root 11928 0.0 0.1 33936 1952 ? Ssl 01:01 0:00 ./redis-server *:7002 [cluster]
root 11932 0.0 0.1 33936 1948 ? Ssl 01:01 0:00 ./redis-server *:7003 [cluster]
root 11936 0.0 0.1 33936 1952 ? Ssl 01:01 0:00 ./redis-server *:7004 [cluster]
root 11940 0.0 0.1 33936 1952 ? Ssl 01:01 0:00 ./redis-server *:7005 [cluster]
root 11944 0.0 0.1 33936 1948 ? Ssl 01:01 0:00 ./redis-server *:7006 [cluster]
root 11948 0.0 0.0 4360 748 pts/2 S+ 01:01 0:00 grep redis
[root@localhost redis-cluster]#

執行創建集群命令

[root@localhost redis-cluster]# pwd
/usr/local/redis/redis-cluster
[root@localhost redis-cluster]# ./redis-trib.rb create --replicas 1 192.168.37.131:7001 192.168.37.131:7002 192.168.37.131:7003 192.168.37.131:7004 192.168.37.131:7005 192.168.37.131:7006

成功啟動信息

>>> Creating cluster
Connecting to node 192.168.37.131:7001: OK
Connecting to node 192.168.37.131:7002: OK
Connecting to node 192.168.37.131:7003: OK
Connecting to node 192.168.37.131:7004: OK
Connecting to node 192.168.37.131:7005: OK
Connecting to node 192.168.37.131:7006: OK
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.37.131:7001
192.168.37.131:7002
192.168.37.131:7003
Adding replica 192.168.37.131:7004 to 192.168.37.131:7001
Adding replica 192.168.37.131:7005 to 192.168.37.131:7002
Adding replica 192.168.37.131:7006 to 192.168.37.131:7003
M: 8b153503b52f83634e04b0077f32ef629ad91ee6 192.168.37.131:7001
slots:0-5460 (5461 slots) master
M: f89799066dd8ecaaa1430559be4ce9c8c87055d8 192.168.37.131:7002
slots:5461-10922 (5462 slots) master
M: 53d698ad56b09f89cfef34850213e2d0a44154dd 192.168.37.131:7003
slots:10923-16383 (5461 slots) master
S: e73204399d08c14def1f71d0c5377cbc757dc4b8 192.168.37.131:7004
replicates 8b153503b52f83634e04b0077f32ef629ad91ee6
S: 1d5dcc8d1ccb6bce55efc3e3aadc690dc77808d8 192.168.37.131:7005
replicates f89799066dd8ecaaa1430559be4ce9c8c87055d8
S: e9458233cb85bd897ff694003e6d8a834eba2b44 192.168.37.131:7006
replicates 53d698ad56b09f89cfef34850213e2d0a44154dd
Can I set the above configuration? (type 'yes' to accept): y
*** Aborting...
[root@localhost redis-cluster]# ./redis-trib.rb create --replicas 1 192.168.37.131:7001 192.168.37.131:7002 192.168.37.131:7003 192.168.37.131:7004 192.168.37.131:7005 192.168.37.131:7006
>>> Creating cluster
Connecting to node 192.168.37.131:7001: OK
Connecting to node 192.168.37.131:7002: OK
Connecting to node 192.168.37.131:7003: OK
Connecting to node 192.168.37.131:7004: OK
Connecting to node 192.168.37.131:7005: OK
Connecting to node 192.168.37.131:7006: OK
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.37.131:7001
192.168.37.131:7002
192.168.37.131:7003
Adding replica 192.168.37.131:7004 to 192.168.37.131:7001
Adding replica 192.168.37.131:7005 to 192.168.37.131:7002
Adding replica 192.168.37.131:7006 to 192.168.37.131:7003
M: 8b153503b52f83634e04b0077f32ef629ad91ee6 192.168.37.131:7001

slots:0-5460 (5461 slots) master
M: f89799066dd8ecaaa1430559be4ce9c8c87055d8 192.168.37.131:7002
slots:5461-10922 (5462 slots) master
M: 53d698ad56b09f89cfef34850213e2d0a44154dd 192.168.37.131:7003
slots:10923-16383 (5461 slots) master
S: e73204399d08c14def1f71d0c5377cbc757dc4b8 192.168.37.131:7004
replicates 8b153503b52f83634e04b0077f32ef629ad91ee6
S: 1d5dcc8d1ccb6bce55efc3e3aadc690dc77808d8 192.168.37.131:7005
replicates f89799066dd8ecaaa1430559be4ce9c8c87055d8
S: e9458233cb85bd897ff694003e6d8a834eba2b44 192.168.37.131:7006
replicates 53d698ad56b09f89cfef34850213e2d0a44154dd
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join.....
>>> Performing Cluster Check (using node 192.168.37.131:7001)
M: 8b153503b52f83634e04b0077f32ef629ad91ee6 192.168.37.131:7001
slots:0-5460 (5461 slots) master
M: f89799066dd8ecaaa1430559be4ce9c8c87055d8 192.168.37.131:7002
slots:5461-10922 (5462 slots) master
M: 53d698ad56b09f89cfef34850213e2d0a44154dd 192.168.37.131:7003
slots:10923-16383 (5461 slots) master
M: e73204399d08c14def1f71d0c5377cbc757dc4b8 192.168.37.131:7004
slots: (0 slots) master
replicates 8b153503b52f83634e04b0077f32ef629ad91ee6
M: 1d5dcc8d1ccb6bce55efc3e3aadc690dc77808d8 192.168.37.131:7005
slots: (0 slots) master
replicates f89799066dd8ecaaa1430559be4ce9c8c87055d8
M: e9458233cb85bd897ff694003e6d8a834eba2b44 192.168.37.131:7006
slots: (0 slots) master
replicates 53d698ad56b09f89cfef34850213e2d0a44154dd
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@localhost redis-cluster]#

異常

>>> Creating cluster
Connecting to node 192.168.37.131:7001: OK
[ERR] Node 192.168.37.131:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.

解決方法是刪除生成的配置文件nodes.conf,如果不行則說明現在創建的結點包括了舊集群的結點信息,需要刪除redis的持久化文件後再重啟redis,比如:appendonly.aof、dump.rdb

首先,使用stop-all.sh停止服務

[root@localhost redis-cluster]# ./stop-all.sh
[root@localhost redis-cluster]# ps aux | grep redis
root 2924 0.8 0.1 33932 2048 ? Ssl Nov01 3:54 ./redis-server *:6379 [cluster]
root 11969 0.0 0.0 4360 744 pts/2 S+ 01:10 0:00 grep redis
[root@localhost redis-cluster]#

然後每個節點中的appendonly.aof、dump.rdb 、nodes.conf。

[root@localhost redis-cluster]# rm -f redis*/dump.rdb
[root@localhost redis-cluster]# rm -f redis*/appendonly.aof
[root@localhost redis-cluster]# rm -f redis*/nodes.conf

然後使用腳本start-all.sh啟動,再啟動集群管理服務。

[root@localhost redis-cluster]# ./start-all.sh 
[root@localhost redis-cluster]# ps aux | grep redis
root 2924 0.8 0.1 33932 2048 ? Ssl Nov01 3:54 ./redis-server *:6379 [cluster]
root 11980 0.0 0.1 33936 1952 ? Ssl 01:12 0:00 ./redis-server *:7001 [cluster]
root 11982 0.0 0.1 33936 1952 ? Ssl 01:12 0:00 ./redis-server *:7002 [cluster]
root 11984 0.0 0.1 33936 1952 ? Ssl 01:12 0:00 ./redis-server *:7003 [cluster]
root 11986 0.0 0.1 33936 1952 ? Ssl 01:12 0:00 ./redis-server *:7004 [cluster]
root 11988 0.0 0.1 33936 1948 ? Ssl 01:12 0:00 ./redis-server *:7005 [cluster]
root 11990 0.0 0.1 33936 1948 ? Ssl 01:12 0:00 ./redis-server *:7006 [cluster]
root 12004 0.0 0.0 4360 748 pts/2 S+ 01:12 0:00 grep redis
[root@localhost redis-cluster]# ./redis-trib.rb create --replicas 1 192.168.37.131:7001 192.168.37.131:7002 192.168.37.131:7003 192.168.37.131:7004 192.168.37.131:7005 192.168.37.131:7006
[root@localhost redis-cluster]#

Redis集群節點的操作 查詢集群信息 集群創建成功登陸任意redis結點查詢集群中的節點情況。

客戶端以集群方式登陸:

[root@localhost redis-cluster]# ./redis1/redis-cli -c -h 192.168.37.131 -p 7001 192.168.37.131:7001>

說明: ./redis1/redis-cli -c -h 192.168.37.131 -p 7001 ,其中-c表示以集群方式連接redis,-h指定ip地址,-p指定端口號

cluster nodes 查詢集群結點信息

192.168.37.131:7001> cluster nodes
8e1186475f87c928e8a146d3804d9a2697246ad0 192.168.37.131:7003 master - 0 1478085160899 3 connected 10923-16383
80de7003738f74134a3403fc939fed253b7774f2 192.168.37.131:7004 master - 0 1478085156858 8 connected 0-5460
652caf5daf7971135679951324eba7b50e99251a 192.168.37.131:7005 slave 3adba62fdcc331ce231ca580cd2c8701e047bc6d 0 1478085158876 9 connected
1cd6482fd7038d78ad556b52b0cb9e2590ad5598 192.168.37.131:7001 myself,slave 80de7003738f74134a3403fc939fed253b7774f2 0 0 1 connected
3adba62fdcc331ce231ca580cd2c8701e047bc6d 192.168.37.131:7002 master - 0 1478085159889 9 connected 5461-10922
cf23ca6d78cba3d3924065e1f7a394f6c51d4b28 192.168.37.131:7006 slave 8e1186475f87c928e8a146d3804d9a2697246ad0 0 1478085157867 6 connected
192.168.37.131:7001>

cluster info 查詢集群狀態信息

192.168.37.131:7001> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:9
cluster_my_epoch:8
cluster_stats_messages_sent:12727
cluster_stats_messages_received:10820
192.168.37.131:7001>

添加主節點 集群創建成功後可以向集群中添加節點,下面是添加一個master主節點。

首先,準備一個乾淨的redis節點。按上面集群版修改redis配置文件。開啟該redis節點。

查看redis進程

[root@localhost redis-cluster]# !ps
ps aux | grep redis
root 2924 0.6 0.1 33932 1800 ? Ssl Nov01 4:08 ./redis-server *:6379 [cluster]
root 11980 0.0 0.2 33936 2216 ? Ssl 01:12 0:09 ./redis-server *:7001 [cluster]
root 11982 0.0 0.2 33936 2244 ? Ssl 01:12 0:09 ./redis-server *:7002 [cluster]
root 11984 0.0 0.2 33936 2220 ? Ssl 01:12 0:09 ./redis-server *:7003 [cluster]

root 11986 0.0 0.2 33936 2216 ? Ssl 01:12 0:09 ./redis-server *:7004 [cluster]
root 11988 0.0 0.2 33936 2228 ? Ssl 01:12 0:09 ./redis-server *:7005 [cluster]
root 11990 0.0 0.2 33936 2212 ? Ssl 01:12 0:09 ./redis-server *:7006 [cluster]
root 13913 0.0 0.1 33936 1952 ? Ssl 04:21 0:00 ./redis7/redis-server *:7007 [cluster]
root 13917 0.0 0.0 4360 728 pts/3 S+ 04:21 0:00 grep redis
[root@localhost redis-cluster]#

執行下邊命令:

[root@localhost redis-cluster]# ./redis-trib.rb add-node 192.168.37.131:7007 192.168.37.131:7001
>>> Adding node 192.168.37.131:7007 to cluster 192.168.37.131:7001
Connecting to node 192.168.37.131:7001: OK
Connecting to node 192.168.37.131:7003: OK
Connecting to node 192.168.37.131:7004: OK
Connecting to node 192.168.37.131:7005: OK
Connecting to node 192.168.37.131:7002: OK
Connecting to node 192.168.37.131:7006: OK
>>> Performing Cluster Check (using node 192.168.37.131:7001)
S: 1cd6482fd7038d78ad556b52b0cb9e2590ad5598 192.168.37.131:7001
slots: (0 slots) slave
replicates 80de7003738f74134a3403fc939fed253b7774f2
M: 8e1186475f87c928e8a146d3804d9a2697246ad0 192.168.37.131:7003
slots:10923-16383 (5461 slots) master
1 additional replica(s)
M: 80de7003738f74134a3403fc939fed253b7774f2 192.168.37.131:7004
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 652caf5daf7971135679951324eba7b50e99251a 192.168.37.131:7005
slots: (0 slots) slave
replicates 3adba62fdcc331ce231ca580cd2c8701e047bc6d
M: 3adba62fdcc331ce231ca580cd2c8701e047bc6d 192.168.37.131:7002
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: cf23ca6d78cba3d3924065e1f7a394f6c51d4b28 192.168.37.131:7006
slots: (0 slots) slave
replicates 8e1186475f87c928e8a146d3804d9a2697246ad0
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
Connecting to node 192.168.37.131:7007: OK
>>> Send CLUSTER MEET to node 192.168.37.131:7007 to make it join the cluster.
[OK] New node added correctly.
[root@localhost redis-cluster]#

查看集群結點發現7007已添加到集群中:

[root@localhost redis-cluster]# ./redis1/redis-cli -c -h 192.168.37.131 -p 7001
192.168.37.131:7001> cluster nodes
8e1186475f87c928e8a146d3804d9a2697246ad0 192.168.37.131:7003 master - 0 1478085870038 3 connected 10923-16383
80de7003738f74134a3403fc939fed253b7774f2 192.168.37.131:7004 master - 0 1478085868020 8 connected 0-5460
652caf5daf7971135679951324eba7b50e99251a 192.168.37.131:7005 slave 3adba62fdcc331ce231ca580cd2c8701e047bc6d 0 1478085874075 9 connected
1cd6482fd7038d78ad556b52b0cb9e2590ad5598 192.168.37.131:7001 myself,slave 80de7003738f74134a3403fc939fed253b7774f2 0 0 1 connected
3adba62fdcc331ce231ca580cd2c8701e047bc6d 192.168.37.131:7002 master - 0 1478085873064 9 connected 5461-10922
cf23ca6d78cba3d3924065e1f7a394f6c51d4b28 192.168.37.131:7006 slave 8e1186475f87c928e8a146d3804d9a2697246ad0 0 1478085875086 6 connected
5d6c61ecff23bff3b0fb01a86c66d882f2d402a0 192.168.37.131:7007 master - 0 1478085872056 0 connected
192.168.37.131:7001>

hash槽重新分配 添加完主節點需要對主節點進行hash槽分配這樣該主節才可以存儲數據。 redis集群有16384個槽,集群中的每個master結點分配一些槽,通過查看集群結點可以看到槽佔用情況。

給剛添加的7007結點分配槽:

第一步:連接上集群

./redis-trib.rb reshard 192.168.37.131:7001(連接集群中任意一個可用結點都行)
[root@localhost redis-cluster]# ./redis-trib.rb reshard 192.168.37.131:7001
Connecting to node 192.168.37.131:7001: OK
Connecting to node 192.168.37.131:7003: OK
Connecting to node 192.168.37.131:7004: OK
Connecting to node 192.168.37.131:7005: OK
Connecting to node 192.168.37.131:7002: OK
Connecting to node 192.168.37.131:7006: OK
Connecting to node 192.168.37.131:7007: OK
>>> Performing Cluster Check (using node 192.168.37.131:7001)
S: 1cd6482fd7038d78ad556b52b0cb9e2590ad5598 192.168.37.131:7001
slots: (0 slots) slave
replicates 80de7003738f74134a3403fc939fed253b7774f2
M: 8e1186475f87c928e8a146d3804d9a2697246ad0 192.168.37.131:7003
slots:10923-16383 (5461 slots) master
1 additional replica(s)
M: 80de7003738f74134a3403fc939fed253b7774f2 192.168.37.131:7004
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 652caf5daf7971135679951324eba7b50e99251a 192.168.37.131:7005

slots: (0 slots) slave
replicates 3adba62fdcc331ce231ca580cd2c8701e047bc6d
M: 3adba62fdcc331ce231ca580cd2c8701e047bc6d 192.168.37.131:7002
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: cf23ca6d78cba3d3924065e1f7a394f6c51d4b28 192.168.37.131:7006
slots: (0 slots) slave
replicates 8e1186475f87c928e8a146d3804d9a2697246ad0
M: 5d6c61ecff23bff3b0fb01a86c66d882f2d402a0 192.168.37.131:7007
slots: (0 slots) master
0 additional replica(s)
[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)?

第二步:輸入要分配的槽數量

How many slots do you want to move (from 1 to 16384)? 1000 What is the receiving node ID?

輸入1000表示要分配1000個槽

第三步:輸入接收槽的結點id

這裡準備給7007分配槽,通過cluster nodes查看7007結點id為5d6c61ecff23bff3b0fb01a86c66d882f2d402a0

輸入:5d6c61ecff23bff3b0fb01a86c66d882f2d402a0

What is the receiving node ID? 5d6c61ecff23bff3b0fb01a86c66d882f2d402a0
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:

第四步:輸入源結點id 輸入源結點id,槽將從源結點中拿,分配後的槽在源結點中就不存在了。 輸入all表示從所有源結點中獲取槽。 輸入done取消分配。

這裡輸入all

Source node #1:all

省略了很多

 Moving slot 11253 from 8e1186475f87c928e8a146d3804d9a2697246ad0
Moving slot 11254 from 8e1186475f87c928e8a146d3804d9a2697246ad0
Moving slot 11255 from 8e1186475f87c928e8a146d3804d9a2697246ad0
Do you want to proceed with the proposed reshard plan (yes/no)?

第五步:輸入yes開始移動槽到目標結點id

省略了很多

Moving slot 11253 from 192.168.37.131:7003 to 192.168.37.131:7007: 
Moving slot 11254 from 192.168.37.131:7003 to 192.168.37.131:7007:
Moving slot 11255 from 192.168.37.131:7003 to 192.168.37.131:7007:
[root@localhost redis-cluster]#

第六步:查看結點信息

[root@localhost redis-cluster]# ./redis1/redis-cli -c -h 192.168.37.131 -p 7001
192.168.37.131:7001> cluster nodes
8e1186475f87c928e8a146d3804d9a2697246ad0 192.168.37.131:7003 master - 0 1478086754466 3 connected 11256-16383
80de7003738f74134a3403fc939fed253b7774f2 192.168.37.131:7004 master - 0 1478086758509 8 connected 333-5460
652caf5daf7971135679951324eba7b50e99251a 192.168.37.131:7005 slave 3adba62fdcc331ce231ca580cd2c8701e047bc6d 0 1478086756490 9 connected
1cd6482fd7038d78ad556b52b0cb9e2590ad5598 192.168.37.131:7001 myself,slave 80de7003738f74134a3403fc939fed253b7774f2 0 0 1 connected
3adba62fdcc331ce231ca580cd2c8701e047bc6d 192.168.37.131:7002 master - 0 1478086757500 9 connected 5795-10922
cf23ca6d78cba3d3924065e1f7a394f6c51d4b28 192.168.37.131:7006 slave 8e1186475f87c928e8a146d3804d9a2697246ad0 0 1478086755477 6 connected
5d6c61ecff23bff3b0fb01a86c66d882f2d402a0 192.168.37.131:7007 master - 0 1478086759518 10 connected 0-332 5461-5794 10923-11255
192.168.37.131:7001>

查看結點信息,可以發現7007結點已經從三個主節點中獲取了slot。

添加從節點 集群創建成功後可以向集群中添加節點,下面是添加一個slave從節點。 添加7008從結點,將7008作為7007的從結點。

首先,準備一個乾淨的redis節點。按上面集群版修改redis配置文件。開啟該redis節點。

查看redis進程

[root@localhost redis-cluster]# ps aux | grep redis
root 2924 0.5 0.1 33932 1800 ? Ssl Nov01 4:12 ./redis-server *:6379 [cluster]
root 11980 0.0 0.2 33936 2308 ? Ssl 01:12 0:13 ./redis-server *:7001 [cluster]
root 11982 0.0 0.2 33936 2288 ? Ssl 01:12 0:13 ./redis-server *:7002 [cluster]
root 11984 0.0 0.2 33936 2236 ? Ssl 01:12 0:13 ./redis-server *:7003 [cluster]
root 11986 0.0 0.2 33936 2288 ? Ssl 01:12 0:13 ./redis-server *:7004 [cluster]
root 11988 0.0 0.2 33936 2248 ? Ssl 01:12 0:13 ./redis-server *:7005 [cluster]
root 11990 0.0 0.2 33936 2244 ? Ssl 01:12 0:13 ./redis-server *:7006 [cluster]
root 13913 0.1 0.2 33936 2092 ? Ssl 04:21 0:04 ./redis7/redis-server *:7007 [cluster]
root 14000 0.1 0.1 33936 1948 ? Ssl 05:24 0:00 ./redis-server *:7008 [cluster]
root 14006 0.0 0.0 4360 732 pts/3 S+ 05:24 0:00 grep redis
[root@localhost redis-cluster]#

命令格式為:

./redis-trib.rb add-node --slave --master-id 主節點id 添加節點的ip和端口 集群中已存在節點ip和端口 執行如下命令:

[root@localhost redis-cluster]# ./redis-trib.rb add-node --slave --master-id 5d6c61ecff23bff3b0fb01a86c66d882f2d402a0 192.168.37.131:7008 192.168.37.131:7001
>>> Adding node 192.168.37.131:7008 to cluster 192.168.37.131:7001
Connecting to node 192.168.37.131:7001: OK
Connecting to node 192.168.37.131:7003: OK
Connecting to node 192.168.37.131:7004: OK
Connecting to node 192.168.37.131:7005: OK
Connecting to node 192.168.37.131:7002: OK
Connecting to node 192.168.37.131:7006: OK
Connecting to node 192.168.37.131:7007: OK
>>> Performing Cluster Check (using node 192.168.37.131:7001)
S: 1cd6482fd7038d78ad556b52b0cb9e2590ad5598 192.168.37.131:7001
slots: (0 slots) slave
replicates 80de7003738f74134a3403fc939fed253b7774f2
M: 8e1186475f87c928e8a146d3804d9a2697246ad0 192.168.37.131:7003
slots:11256-16383 (5128 slots) master
1 additional replica(s)
M: 80de7003738f74134a3403fc939fed253b7774f2 192.168.37.131:7004
slots:333-5460 (5128 slots) master
1 additional replica(s)
S: 652caf5daf7971135679951324eba7b50e99251a 192.168.37.131:7005

slots: (0 slots) slave
replicates 3adba62fdcc331ce231ca580cd2c8701e047bc6d
M: 3adba62fdcc331ce231ca580cd2c8701e047bc6d 192.168.37.131:7002
slots:5795-10922 (5128 slots) master
1 additional replica(s)
S: cf23ca6d78cba3d3924065e1f7a394f6c51d4b28 192.168.37.131:7006
slots: (0 slots) slave
replicates 8e1186475f87c928e8a146d3804d9a2697246ad0
M: 5d6c61ecff23bff3b0fb01a86c66d882f2d402a0 192.168.37.131:7007
slots:0-332,5461-5794,10923-11255 (1000 slots) master
0 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
Connecting to node 192.168.37.131:7008: OK
>>> Send CLUSTER MEET to node 192.168.37.131:7008 to make it join the cluster.
Waiting for the cluster to join.
>>> Configure node as replica of 192.168.37.131:7007.
[OK] New node added correctly.
[root@localhost redis-cluster]#

5d6c61ecff23bff3b0fb01a86c66d882f2d402a0是7007結點的id,可以通過cluster nodes查看。

查看集群中的結點,剛添加的7008為7007的從節點:

[root@localhost redis-cluster]# ./redis1/redis-cli -p 7001 -c 127.0.0.1:7001> cluster nodes
8e1186475f87c928e8a146d3804d9a2697246ad0 192.168.37.131:7003 master - 0 1478089964769 3 connected 11256-16383
80de7003738f74134a3403fc939fed253b7774f2 192.168.37.131:7004 master - 0 1478089966584 8 connected 333-5460
652caf5daf7971135679951324eba7b50e99251a 192.168.37.131:7005 slave 3adba62fdcc331ce231ca580cd2c8701e047bc6d 0 1478089963748 9 connected
1cd6482fd7038d78ad556b52b0cb9e2590ad5598 192.168.37.131:7001 myself,slave 80de7003738f74134a3403fc939fed253b7774f2 0 0 1 connected
3adba62fdcc331ce231ca580cd2c8701e047bc6d 192.168.37.131:7002 master - 0 1478089966787 9 connected 5795-10922
cf23ca6d78cba3d3924065e1f7a394f6c51d4b28 192.168.37.131:7006 slave 8e1186475f87c928e8a146d3804d9a2697246ad0 0 1478089962729 6 connected
5c97e8eab019c40ea3df4925c7400fe7df1846bb 192.168.37.131:7008 slave 5d6c61ecff23bff3b0fb01a86c66d882f2d402a0 0 1478089961713 10 connected
5d6c61ecff23bff3b0fb01a86c66d882f2d402a0 192.168.37.131:7007 master - 0 1478089965777 10 connected 0-332 5461-5794 10923-11255
127.0.0.1:7001>

刪除結點 ./redis-trib.rb del-node 192.168.37.131:7007 5d6c61ecff23bff3b0fb01a86c66d882f2d402a0 刪除已經佔有hash槽的結點會失敗,報錯如下:

[ERR] Node 192.168.37.131:7007 is not empty! Reshard data away and try again. 需要將該結點佔用的hash槽分配出去,請參考《hash槽重新分配》這段內容。

客戶端對Redis集群的使用方法 使用redis命令行客戶端連接

[root@localhost redis-cluster]# ./redis1/redis-cli -p 7001 -c
127.0.0.1:7001> get a
-> Redirected to slot [15495] located at 192.168.37.131:7003
(nil)
192.168.37.131:7003>

一定要加-c參數,節點之間就可以互相跳轉

使用jedis連接

package com.pc.jedis.test;

import java.util.HashSet;
import java.util.Set;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

/**
* Jedis集群測試
*
* @author Switch
* @data 2017年2月11日
* @version V1.0
*/
public class JedisClusterTest {
public static void main(String[] args) {
// 創建並填充節點信息
Set<hostandport> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.37.131", 7001));
nodes.add(new HostAndPort("192.168.37.131", 7002));
nodes.add(new HostAndPort("192.168.37.131", 7003));
nodes.add(new HostAndPort("192.168.37.131", 7004));
nodes.add(new HostAndPort("192.168.37.131", 7005));
nodes.add(new HostAndPort("192.168.37.131", 7006));

// 創建JedisCluster對象
JedisCluster jedisCluster = new JedisCluster(nodes);

// 使用jedisCluster操作redis

String key = "jedisCluster";
String setResult = jedisCluster.set(key, "hello redis!");
System.out.println(setResult);

String getResult = jedisCluster.get(key);
System.out.println(getResult);

// 關閉jedisCluster(程序執行完後才能關閉,內部封裝了連接池)
jedisCluster.close();
}
}
/<hostandport>

#

參考《Redis官方文檔》


分享到:


相關文章: