redis cluster在設計的時候,就考慮到了去中心化,去中間件,也就是說,集羣中的每一個節點都是平等的關係,都是對等的,每一個節點都保存各自的數據和整個集羣的狀態。
每一個節點都和其餘全部節點鏈接,並且這些鏈接保持活躍,這樣就保證了咱們只須要鏈接集羣中的任意一個節點,就能夠獲取到其餘節點的數據。 Redis 集羣沒有並使用傳統的一致性哈希來分配數據,而是採用另一種叫作哈希槽 (hash slot)的方式來分配的。
redis cluster 默認分配了 16384 個slot,當咱們set一個key 時,會用CRC16算法來取模獲得所屬的slot,而後將這個key 分到哈希槽區間的節點上,具體算法就是:CRC16(key) % 16384。
因此咱們在測試的時候看到set 和 get 的時候,直接跳轉到了7001端口的節點。 Redis 集羣會把數據存在一個 master 節點,而後在這個 master 和其對應的salve 之間進行數據同步。
當讀取數據時,也根據一致性哈希算法到對應的 master 節點獲取數據。只有當一個master 掛掉以後,纔會啓動一個對應的 salve 節點,充當 master 。
解決單點固障,鏈接上集羣中的任務一個節點都能取到數據.
須要注意的是:reids集羣從3.0開始支持的。必需要3個或以上的主節點,不然在建立集羣時會失敗,而且當存活的主節點數小於總節點數的一半時,整個集羣就沒法提供服務了 192.168.23.150 使用的docker node1_redis 172.16.0.10 node2_redis 172.16.0.11 6個redis節點信息: 172.16.0.10:7001 172.16.0.10:7002 172.16.0.10:7003 172.16.0.11:7004 172.16.0.11:7005 172.16.0.11:7006
分別在兩個節點上安裝redis
yum install -y gcc tar -xf redis-3.2.8.tar.gz cd redis-3.2.8 make && make PREFIX=/opt/redis install
#centos7安裝 make MALLOC=libc && make PREFIX=/opt/redis install
cd src
cp redis-trib.rb /opt/redis/bin/
echo "export PATH=$PATH:/opt/redis/bin" >> /etc/profile.d/env.sh
source /etc/profile
分別在兩個節點上建立,別外一臺是7004,7005,7006 建立目錄 cd /opt/redis mkdir -p {data,logs}/redis_cluster/{7001,7002,7003} 準備配置文件redis.conf daemonize yes
protected-mode no #3.2 後的新特性,禁止公網訪問redis cache,增強redis安全的 pidfile /opt/redis/data/redis_cluster/7001/redis_7001.pid port 7001 timeout 300 loglevel debug logfile /opt/redis/data/redis_cluster/7001/redis_7001.log databases 16 save 900 1 save 300 10 save 60 10000 rdbcompression yes dbfilename dump.rdb dir /opt/redis/data/redis_cluster/7001/ cluster-enabled yes #開啓集羣 把註釋#去掉 cluster-config-file nodes_7001.conf #集羣的配置 配置文件首次啓動自動生成 7001,7001,7002 cluster-node-timeout 15000 #請求超時 默認15秒,可自行設置 cp -a redis.conf /opt/redis/data/redis_cluster/7001/ cp -a redis.conf /opt/redis/data/redis_cluster/7002/ cp -a redis.conf /opt/redis/data/redis_cluster/7003/ sed -i 's/7001/7001/g' /opt/redis/data/redis_cluster/7001/redis.conf sed -i 's/7001/7002/g' /opt/redis/data/redis_cluster/7002/redis.conf sed -i 's/7001/7003/g' /opt/redis/data/redis_cluster/7003/redis.conf redis-server /opt/redis/data/redis_cluster/7001/redis.conf redis-server /opt/redis/data/redis_cluster/7002/redis.conf redis-server /opt/redis/data/redis_cluster/7003/redis.conf
安裝依賴
yum -y install ruby ruby-devel rubygems rpm-build
安裝ruby redis 接口
gem install redis #執行這步失敗的話。能夠說明的方式操做 1. Fetching: redis-3.2.2.gem (100%)
2. Successfully installed redis-3.2.2
3. Parsing documentation for redis-3.2.2
4. Installing ri documentation for redis-3.2.2
5. Done installing documentation for redis after 1 seconds
6. 1 gem installed
說明:因爲ruby 官放提供的gem 源被GFW 幹掉了,因此這裏須要從新使用國內的源,方法以下:
移除自帶的源:
gem sources -l
gem sources --remove https://rubygems.org/
添加國內淘寶源:
gem source --add https://ruby.taobao.org/
gem sources -l
gem install redis
報錯:redis requires Ruby version >= 2.2.2
解決:
方法1:採用rvm來更新ruby(很差用)
gpg2 --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
curl -L get.rvm.io | bash -s stable
source /usr/local/rvm/scripts/rvm
rvm list known #查看rvm庫中已知的ruby版本
rvm install 2.3.3
rvm use 2.3.3
rvm use 2.3.3 --default #默認使用版本
rvm remove 2.0.0 #移除2.0.0版本
ruby --version #查看版本
gem install redis
方法2:編譯安裝(好用)
(1)安裝Ruby
wget http://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.5.tar.gz
tar zxvf ruby-2.3.5.tar.gz
cd ruby-2.3.5
./configure --prefix=/opt/ruby
make && make install
ln -s /opt/ruby/bin/ruby /usr/bin/ruby
ln -s /opt/ruby/bin/gem /usr/bin/gem
ruby -v #查看版本
(2)安裝rubygem redis依賴
wget http://rubygems.org/downloads/redis-3.3.0.gem
gem install -l redis-3.3.0.gem
redis-trib.rb #出現幫助文檔,說明成功了
建立集羣 redis-trib.rb create --replicas 1 172.16.0.10:7001 172.16.0.10:7002 172.16.0.10:7003 172.16.0.11:7004 172.16.0.11:7005 172.16.0.11:7006 #--replicas 1 就是這個集羣節點都有一個副本
鏈接方式爲 redis-cli -h 172.16.0.10 -c -p 7002 ,加參數 -c 可鏈接到集羣,由於上面 redis.conf 將 bind 改成了ip地址,因此 -h 參數不能夠省略。
在第一臺機器上鍊接集羣的7002端口的節點,在另一臺鏈接7005節點,鏈接方式爲 redis-cli -h 172.16.0.10 -c -p 7002
,加參數 -c 可鏈接到集羣,由於上面 redis.conf 將 bind 改成了ip地址,因此 -h 參數不能夠省略。 在7005節點執行命令: set hello world 在7002節點執行: get hello 在任何節點上能獲取到hello的值,說明集羣運做正常(注意:用keys *查看不到key.可是get hello 能夠獲取到值,另外能夠在副本節點上面添加數據)
隨便登錄一個redis node節點執行命令: redis-cli -h 172.16.0.10 -c -p 7002 #登錄 cluster nodes #查看節點信息
添加啓動個節點,步聚和上面同樣 執行redis-trib.rb add-node 添加新節點: /opt/src/redis-3.0.5/src/redis-trib.rb add-node 127.0.0.1:7007 127.0.0.1:7001 說明:添加新節點到羣集中,須要指定羣集中任意一個已存在的節點,實例中的第一個IP:PORT 爲新的redis 節點的IP及端口,第二個IP:PORT 爲redis 羣集中已經存在的任意redis 節點。 添加完成,登錄羣集,驗證加入後的新節點變爲主節點: redis-cli -c -h 127.0.0.1:7001 1. 127.0.0.1:7001> cluster nodes 2. 1455e7fe08990793e9663ed14cf9c19778ef01a7 127.0.0.1:7004 slave 5951f796ac2930f73b6988ccb633ab2ea10a873b 0 1447233606830 5 connected 3. 577be6355e37a54c7a076e27ab0927298abcae5f 127.0.0.1:7003 slave 73bf492caa9ba02567581145b5d4f32f9f28e09d 0 1447233608841 4 connected 4. 30117592dc0d31b1c611ca47820f1d820565926e 127.0.0.1:7005 slave 1e157ac10d8292661e80c6ee17f09d2dc94a4b2a 0 1447233607331 6 connected 5. 1e157ac10d8292661e80c6ee17f09d2dc94a4b2a 127.0.0.1:7002 master - 0 1447233607835 3 connected 10923-16383 6. 9868224efa99bca26a171f6e1c21dc11c4e2ab5c 127.0.0.1:7006 master - 0 1447233607331 0 connected 7. 73bf492caa9ba02567581145b5d4f32f9f28e09d 127.0.0.1:7001 myself,master - 0 0 1 connected 0-5460 8. 5951f796ac2930f73b6988ccb633ab2ea10a873b 127.0.0.1:7001 master - 0 1447233607331 2 connected 5461-10922 2.添加從節點: /opt/src/redis-3.0.5/src/redis-trib.rb add-node --slave 127.0.0.1:7008 127.0.0.1:7001 redis-cli -c -p 7001 1. 127.0.0.1:7001> cluster nodes 2. ef275d7c4c1f00ce236011f0c0cd7b4be7eb7772 127.0.0.1:7007 slave 9868224efa99bca26a171f6e1c21dc11c4e2ab5c 0 1447241281594 0 connected 3. 1455e7fe08990793e9663ed14cf9c19778ef01a7 127.0.0.1:7004 slave 5951f796ac2930f73b6988ccb633ab2ea10a873b 0 1447241282095 5 connected 4. 577be6355e37a54c7a076e27ab0927298abcae5f 127.0.0.1:7003 slave 73bf492caa9ba02567581145b5d4f32f9f28e09d 0 1447241282597 4 connected 5. 30117592dc0d31b1c611ca47820f1d820565926e 127.0.0.1:7005 slave 1e157ac10d8292661e80c6ee17f09d2dc94a4b2a 0 1447241281594 6 connected 6. 1e157ac10d8292661e80c6ee17f09d2dc94a4b2a 127.0.0.1:7002 master - 0 1447241283098 3 connected 10923-16383 7. 9868224efa99bca26a171f6e1c21dc11c4e2ab5c 127.0.0.1:7006 master - 0 1447241282095 0 connected 8. 73bf492caa9ba02567581145b5d4f32f9f28e09d 127.0.0.1:7001 myself,master - 0 0 1 connected 0-5460 9. 5951f796ac2930f73b6988ccb633ab2ea10a873b 127.0.0.1:7001 master - 0 1447241283599 2 connected 5461-10922
數據分片,也可稱數據轉移。由第二篇中添加的主節點可知,新的主節點沒有數據,也不能參加主的選舉,因此,爲了該主恩可以正常被選舉,咱們能夠將原有主節點的數據轉移至該節點:
咱們先來看下新主節點:node
192.168.159.30:7003> cluster nodes 4a5799c7a7f53e8700e99be5a7a50d65c4204cac 192.168.159.30:7003 myself,master - 0 0 3 connected 10923-16383 3d76e38836d78b0dc81ac7c0c306b57f2b6a389e 192.168.159.30:7006 slave 4a5799c7a7f53e8700e99be5a7a50d65c4204cac 0 1523528690606 6 connected cc7833a44dd9f9a0157adec82e5afa959d20f29d 192.168.159.30:7004 slave 6d377542e01a23fe5cfc7f8f25365e910480a11a 0 1523528689096 4 connected 869458ad40bb9a2e4dcb870f3c2a4a2a2d3bc257 192.168.159.30:7005 slave 73b5273bfa67693eeb01a5c99c855a333d6214e0 0 1523528688595 5 connected 9078070919bf726e213dfa634d86a5ae1f7a0ae8 127.0.0.1:7008 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523528687589 7 connected 6d377542e01a23fe5cfc7f8f25365e910480a11a 192.168.159.30:7001 master - 0 1523528686584 1 connected 0-5460 73b5273bfa67693eeb01a5c99c855a333d6214e0 192.168.159.30:7002 master - 0 1523528687087 2 connected 5461-10922 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 192.168.159.30:7007 master - 0 1523528689600 7 connected #新加節點沒有數據
從上面的實例中能夠很明顯的看出,有三個從,四個主,當前登陸的主爲7003,且除了主節點7007沒有數據外,其它三個主都有(7001:0-5460;7002:5461-10922;7003:10923-16383)web
如今,我須要從三個節點抽取500個數據槽給新節點 7007,那麼執行redis
redis-trib.rb reshard 127.0.0.1:7007
詢問從1-16384 個插槽中要移動多少數據槽,我這裏是500:算法
How many slots do you want to move (from 1 to 16384)? 500
詢問接收數據槽節點的ID(根據上面的cluster nodes 能夠獲得 7007 的ID):docker
What is the receiving node ID? 9868224efa99bca26a171f6e1c21dc11c4e2ab5c
詢問你是從全部主節點移除500 個數據槽仍是單從某一個主節點中移出 500個數據槽?輸入 all ,表明從全部主節點;若是要從某個節點逸出,那麼只須要輸入該主節點ID,回車便可:centos
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
輸入完成,回車後開始移動數據槽安全
移動完成,再來看各主的數據ruby
192.168.159.30:7003> cluster nodes 4a5799c7a7f53e8700e99be5a7a50d65c4204cac 192.168.159.30:7003 myself,master - 0 0 3 connected 11172-16383 3d76e38836d78b0dc81ac7c0c306b57f2b6a389e 192.168.159.30:7006 slave 4a5799c7a7f53e8700e99be5a7a50d65c4204cac 0 1523530671361 6 connected cc7833a44dd9f9a0157adec82e5afa959d20f29d 192.168.159.30:7004 slave 6d377542e01a23fe5cfc7f8f25365e910480a11a 0 1523530673372 8 connected 869458ad40bb9a2e4dcb870f3c2a4a2a2d3bc257 192.168.159.30:7005 slave 73b5273bfa67693eeb01a5c99c855a333d6214e0 0 1523530675386 5 connected 9078070919bf726e213dfa634d86a5ae1f7a0ae8 127.0.0.1:7008 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523530670360 9 connected 6d377542e01a23fe5cfc7f8f25365e910480a11a 192.168.159.30:7001 master - 0 1523530674379 8 connected 500-5711 10923-11171 73b5273bfa67693eeb01a5c99c855a333d6214e0 192.168.159.30:7002 master - 0 1523530674883 2 connected 5712-10922 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 192.168.159.30:7007 master - 0 1523530672367 9 connected 0-499 #很明顯,主 7006 上已經被分配數據槽了!
上面是從全部主節點中平均抽取數據槽到新的主節點上。bash
==================對單一節點進行===========================app
那麼,咱們也能夠針對單一節點進行,好比,我想將7001 剩餘的數據槽所有轉移到 7007 上,那麼以下:
執行:
redis-trib.rb reshard 127.0.0.1:7007
主節點 7001 上能夠轉移的數據槽:
How many slots do you want to move (from 1 to 16384)? 5295
接收數據節點的ID:
What is the receiving node ID? 9868224efa99bca26a171f6e1c21dc11c4e2ab5c
轉移數據主節點的ID(就是要把哪一個節點的數據轉移出去的節點ID)
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:73bf492caa9ba02567581145b5d4f32f9f28e09d
輸完一個要轉移數據的節點後,會繼續要求輸入第二個節點的ID。因爲這裏我只想轉移主節點7000 上的全部數據,因此,第二個節點ID 我輸入done,表明只須要轉移第一個主節點:
Source node #2:done
詢問你是否確認要執行數據分片:
Do you want to proceed with the proposed reshard plan (yes/no)? yes
再次登陸查看集羣:
192.168.159.30:7003> cluster nodes
4a5799c7a7f53e8700e99be5a7a50d65c4204cac 192.168.159.30:7003 myself,master - 0 0 3 connected 11172-16383
3d76e38836d78b0dc81ac7c0c306b57f2b6a389e 192.168.159.30:7006 slave 4a5799c7a7f53e8700e99be5a7a50d65c4204cac 0 1523531456275 6 connected
cc7833a44dd9f9a0157adec82e5afa959d20f29d 192.168.159.30:7004 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523531457281 9 connected
869458ad40bb9a2e4dcb870f3c2a4a2a2d3bc257 192.168.159.30:7005 slave 73b5273bfa67693eeb01a5c99c855a333d6214e0 0 1523531454767 5 connected
9078070919bf726e213dfa634d86a5ae1f7a0ae8 127.0.0.1:7008 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523531454266 9 connected
6d377542e01a23fe5cfc7f8f25365e910480a11a 192.168.159.30:7001 master - 0 1523531453260 8 connected #能夠看到7001沒有數據了
73b5273bfa67693eeb01a5c99c855a333d6214e0 192.168.159.30:7002 master - 0 1523531455270 2 connected 5712-10922
456cbd75f4a74f818cb396b207b1ad6a3e4a242e 192.168.159.30:7007 master - 0 1523531452253 9 connected 0-5711 10923-11171
redis 羣集中,要刪除節點,必須先將該節點的數據所有轉移,不然是沒法刪除節點的(也就是,redis 羣集中智能刪除空節點):
查看集羣信息:
redis-cli -h 192.168.159.30 -p 7001 -c 192.168.159.30:7001> cluster nodes 3d76e38836d78b0dc81ac7c0c306b57f2b6a389e 192.168.159.30:7006 slave 4a5799c7a7f53e8700e99be5a7a50d65c4204cac 0 1523531623348 6 connected 9078070919bf726e213dfa634d86a5ae1f7a0ae8 127.0.0.1:7008 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523531627894 9 connected 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 127.0.0.1:7007 master - 0 1523531625877 9 connected 0-5711 10923-11171 869458ad40bb9a2e4dcb870f3c2a4a2a2d3bc257 192.168.159.30:7005 slave 73b5273bfa67693eeb01a5c99c855a333d6214e0 0 1523531626887 5 connected cc7833a44dd9f9a0157adec82e5afa959d20f29d 192.168.159.30:7004 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523531624862 9 connected 6d377542e01a23fe5cfc7f8f25365e910480a11a 127.0.0.1:7001 myself,master - 0 0 8 connected #7001沒有數據 73b5273bfa67693eeb01a5c99c855a333d6214e0 192.168.159.30:7002 master - 0 1523531628902 2 connected 5712-10922 4a5799c7a7f53e8700e99be5a7a50d65c4204cac 192.168.159.30:7003 master - 0 1523531623853 3 connected 11172-16383
咱們來嘗試刪除某個帶有數據的主節點:
[root@docker1 ~]# redis-trib.rb del-node 127.0.0.1:7002 '73b5273bfa67693eeb01a5c99c855a333d6214e0' >>> Removing node 73b5273bfa67693eeb01a5c99c855a333d6214e0 from cluster 127.0.0.1:7002 [ERR] Node 127.0.0.1:7002 is not empty! Reshard data away and try again #7002是隨便哪一個能連上集羣的端口,後面的是非空數據的節點ID. 能夠看出非空的節點不能刪除
再次刪除空節點:
redis-trib.rb del-node 127.0.0.1:7002 '6d377542e01a23fe5cfc7f8f25365e910480a11a' >>> Removing node 6d377542e01a23fe5cfc7f8f25365e910480a11a from cluster 127.0.0.1:7002 >>> Sending CLUSTER FORGET messages to the cluster... >>> SHUTDOWN the node. 注:在刪除節點時,不容許使用 redis-trib.rb del-node 刪除節點IP:PORT '刪除節點的ID'.只能用其它節點IP:PORT '要刪除節點的ID'
驗證被刪除:
[root@docker1 ~]# redis-cli -h 192.168.159.30 -p 7002 -c 192.168.159.30:7002> cluster nodes cc7833a44dd9f9a0157adec82e5afa959d20f29d 192.168.159.30:7004 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523532545171 9 connected 9078070919bf726e213dfa634d86a5ae1f7a0ae8 192.168.159.30:7008 slave 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 0 1523532546685 9 connected 456cbd75f4a74f818cb396b207b1ad6a3e4a242e 192.168.159.30:7007 master - 0 1523532548195 9 connected 0-5711 10923-11171 869458ad40bb9a2e4dcb870f3c2a4a2a2d3bc257 192.168.159.30:7005 slave 73b5273bfa67693eeb01a5c99c855a333d6214e0 0 1523532546181 5 connected 73b5273bfa67693eeb01a5c99c855a333d6214e0 192.168.159.30:7002 myself,master - 0 0 2 connected 5712-10922 4a5799c7a7f53e8700e99be5a7a50d65c4204cac 192.168.159.30:7003 master - 0 1523532544157 3 connected 11172-16383 3d76e38836d78b0dc81ac7c0c306b57f2b6a389e 192.168.159.30:7006 slave 4a5799c7a7f53e8700e99be5a7a50d65c4204cac 0 1523532547190 6 connected 注#能夠看出7001已經被刪除了,上面刪除的id就是7001的