Redis 集群提供了以下兩個好處
#將數據自動切分(split)到多個節點的能力。
#當集群中的一部分節點失效或者無法進行通訊時, 仍然可以繼續處理命令請求的能力。
Redis 架構
架構細節:
(1)所有的redis節點彼此互聯(PING-PONG機制),內部使用二進制協議優化傳輸速度和帶寬.
(2)節點的fail是通過集群中超過半數的節點檢測失效時才生效.
(3)客戶端與redis節點直連,不需要中間proxy層.客戶端不需要連接集群所有節點,連接集群中任何一個可用節點即可
(4)redis-cluster把所有的物理節點映射到[0-16383]slot上,cluster 負責維護node<->slot<->value
Redis Cluster 搭建與使用
要讓集群正常工作至少需要3個主節點,在這裡我們要創建6個redis節點,其中三個為主節點,三個為從節點,對應的redis節點的ip和端口對應關係如下(為了簡單演示都在同一台機器上面)。
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]
創建存放多個實例的目錄
mkdir /home/pi/data/cluster -p
cd /home/pi/data/cluster
mkdir 7000 7001 7002 7003 7004 7005
修改配置文件
樹莓派
cp /etc/redis.conf /home/pi/data/cluster/7000/
Linux
cp /home/pi/redis-4.0.2/redis.conf /home/pi/data/cluster/7000/
修改以下選項(修改完成後,把修改完成的redis.conf複製到7001-7005目錄下,並且端口修改成和文件夾對應):
port 7000
daemonize yes —> 即默認以後台程序方式運行
cluster-enabled yes —> 文件中的 cluster-enabled 選項用於開實例的集群模式
cluster-config-file nodes.conf —> cluster-conf-file 選項則設定了保存節點配置文件的路徑, 默認值為nodes.conf
cluster-node-timeout 5000
appendonly yes —> 開啟 AOF 模式
複製 redis.conf 到以下目錄並改寫 port(7001、7002、7003、7004、7005 )
cp /home/pi/data/cluster/7000/redis.conf /home/pi/data/cluster/7001/
cp /home/pi/data/cluster/7000/redis.conf /home/pi/data/cluster/7002/
cp /home/pi/data/cluster/7000/redis.conf /home/pi/data/cluster/7003/
cp /home/pi/data/cluster/7000/redis.conf /home/pi/data/cluster/7004/
cp /home/pi/data/cluster/7000/redis.conf /home/pi/data/cluster/7005/
按上述步驟重複修改 port 屬性
分別啟動 6 個 redis 實例
樹莓派
#0
cd /home/pi/data/cluster/7000
redis-server redis.conf
#1
cd /home/pi/data/cluster/7001
redis-server redis.conf
#2
cd /home/pi/data/cluster/7002
redis-server redis.conf
#3
cd /home/pi/data/cluster/7003
redis-server redis.conf
#4
cd /home/pi/data/cluster/7004
redis-server redis.conf
#5
cd /home/pi/data/cluster/7005
redis-server redis.conf
查看進程是否存在ps -ef | grep redis
檢查是否端口為進程netstat -npl
[執行命令創建 cluster]
安裝ruby相關的環境,否則創建集群可能會失敗sudo apt-get install rubygems
安裝運行需要依賴的ruby的包 gem-redis
必須與 redis 安裝版本一致
cd ~
gem install -l redis-4.0.1.gem
異常處理
gem-redis 必需搭配 Ruby 2.2 以上版本
研究-RVM、ruby
複製集群管理程序到/usr/local/bin
cd /home/pi/Downloads/redis-4.0.1
sudo cp /home/pi/Downloads/redis-4.0.1/src/redis-trib.rb /usr/local/bin/redis-trib
創建集群
執行前先確定 aof、rdb、nodes.conf 個別資料夾已先刪除
192.168.43.176
redis-trib create --replicas 1 192.168.43.176:7000 192.168.43.176:7001 192.168.43.176:7002 192.168.43.176:7003 192.168.43.176:7004 192.168.43.176:7005
127.0.0.1
redis-trib 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
異常處理
pi@MyPi1:/usr/local/bin $ redis-trib 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
>>> Creating cluster
[ERR] Node 127.0.0.1:7000 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
解決辦法
將每個節點下aof、rdb、nodes.conf本地備份文件刪除 (7000、7001、7002、7003、7004、7005)
之後再執行此腳本,成功執行
命令的意義如下:
輸入 yes 並按確認之後, 集群就會將配置應用到各個節點, 並連接起(join)各個節點,各個節點開始互相通訊
一切正常後輸出以下信息
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
測試 Redis 集群比較簡單的辦法就是使用 redis-rb-cluster 或者 redis-cli , 接下來我們將使用 redis-cli 為例來進行演示:
redis-cli -c -p 7001
set name kevin
get name
可以查詢相關指令透過以下命令:可以看見有add-node,不用想了,肯定是添加節點。那麼del-node就是刪除節點。還有check肯定就是檢查狀態了。
[root@redis-server ~]# redis-trib help
Usage: redis-trib <command> <options> <arguments ...>
set-timeout host:port milliseconds
add-node new_host:new_port existing_host:existing_port
--master-id <arg>
--slave
fix host:port
help (show this help)
del-node host:port node_id
import host:port
--from <arg>
check host:port
call host:port command arg arg .. arg
create host1:port1 ... hostN:portN
--replicas <arg>
reshard host:port
--yes
--to <arg>
--from <arg>
--slots <arg>
For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.
[root@redis-server ~]#
可以看到7000-7002是master,7003-7005是slave。redis-cli -h 192.168.43.176 -p 7000 cluster nodes
[故障轉移測試]
可以看見7001是正常的,並且獲取到了key,value,現在kill掉7000實例,再進行查詢。
[root@redis-server ~]# ps -ef | grep 7000
root 4168 1 0 11:49 ? 00:00:03 redis-server *:7000 [cluster]
root 4385 4361 0 12:39 pts/3 00:00:00 grep 7000
[root@redis-server ~]# kill 4168
[root@redis-server ~]# ps -ef | grep 7000
root 4387 4361 0 12:39 pts/3 00:00:00 grep 7000
[root@redis-server ~]# redis-cli -c -p 7001
127.0.0.1:7001> get name
"yayun"
127.0.0.1:7001>
可以正常獲取到value,現在看看狀態。
[root@redis-server ~]# redis-cli -c -p 7001 cluster nodes
2d03b862083ee1b1785dba5db2987739cf3a80eb 127.0.0.1:7001 myself,master - 0 0 2 connected 5461-10922
0456869a2c2359c3e06e065a09de86df2e3135ac 127.0.0.1:7002 master - 0 1428295271619 3 connected 10923-16383
37b251500385929d5c54a005809377681b95ca90 127.0.0.1:7003 master - 0 1428295270603 7 connected 0-5460
e2e2e692c40fc34f700762d1fe3a8df94816a062 127.0.0.1:7004 slave 2d03b862083ee1b1785dba5db2987739cf3a80eb 0 1428295272642 5 connected
2774f156af482b4f76a5c0bda8ec561a8a1719c2 127.0.0.1:7000 master,fail - 1428295159553 1428295157205 1 disconnected
9923235f8f2b2587407350b1d8b887a7a59de8db 127.0.0.1:7005 slave 0456869a2c2359c3e06e065a09de86df2e3135ac 0 1428295269587 6 connected
[root@redis-server ~]#
原來的7000端口實例已經顯示fail,原來的7003是slave,現在自動提升為master。
關於更多的在線添加節點,刪除節點,以及對集群進行重新分片請參考官方文檔。
[Java 集群測試]
使用Java客戶端對Redis進行操作
package com.agile.example.redis;
import java.io.IOException;
import java.util.HashSet;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
/**
* Redis cluseter test
*
* @author Kevin
* @date 2017-11-16
*/
public class RedisClusterTest {
public static void main(String[] args) throws IOException {
HashSet<HostAndPort> nodes = new HashSet<HostAndPort>();
nodes.add(new HostAndPort("192.168.43.176", 7000));
nodes.add(new HostAndPort("192.168.43.176", 7001));
nodes.add(new HostAndPort("192.168.43.176", 7002));
nodes.add(new HostAndPort("192.168.43.176", 7003));
nodes.add(new HostAndPort("192.168.43.176", 7004));
nodes.add(new HostAndPort("192.168.43.176", 7005));
JedisCluster cluster = new JedisCluster(nodes);
cluster.set("jedisClusterKey", "hello world");
String str = cluster.get("jedisClusterKey");
System.out.println("---" + str);
cluster.close(); // 關閉連接
}
}
參考資源
[1] 多節點 安裝redis cluster安裝部署-4.0.1