一、新建一個docker橋接網絡
# 創建名稱爲redis-cluster-net的橋接網絡
docker network create -d bridge redis-cluster-net
二、部署redis節點
參照我的這篇文章中的第二節,部署6個redis節點,綁定到宿主機的端口號分別爲6391~6396,需修改的redis.conf配置如下
#bind 127.0.0.1
protected-mode no
cluster-enabled yes
三、使用redis-trib工具創建集羣
這個工具是redis自帶的,但是不能直接在docker中運行,因爲這個工具需要python運行環境,而默認的redis鏡像是沒有python環境的,因此有兩種辦法運行這個工具:一是自己製作一個帶有這個工具命令的docker鏡像,並支持python環境;二是直接使用別人做好的redis-trib鏡像,這裏我就直接用docker hub上現成的鏡像了。
在命令行運行以下命令,創建redis cluster集羣
docker run -it --network redis-cluster-net zvelo/redis-trib create --replicas 1 172.22.0.2:6379 172.22.0.3:6379 172.22.0.4:6379 172.22.0.5:6379 172.22.0.6:6379 172.22.0.7:6379
-it
表示以交互模式運行容器,因爲創建redis集羣的過程中需要用戶確認一些信息後才能繼續往下執行zvelo/redis-trib
是別人創建的redis-trib工具鏡像,會在運行容器前自動下載該鏡像create --replicas 1 172.22.0.2:6379 172.22.0.3:6379 172.22.0.4:6379 172.22.0.5:6379 172.22.0.6:6379 172.22.0.7:6379
表示創建redis cluster集羣,默認前面3個爲主節點,後面3個爲從節點,172.22.0.x
IP地址是各個redis容器在redis-cluster-net網絡中的IP地址
命令運行過程中的輸出信息如下:
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
172.22.0.2:6379
172.22.0.3:6379
172.22.0.4:6379
Adding replica 172.22.0.5:6379 to 172.22.0.2:6379
Adding replica 172.22.0.6:6379 to 172.22.0.3:6379
Adding replica 172.22.0.7:6379 to 172.22.0.4:6379
M: 508a55e8eb9caa4962c21ac6a5374ef15bfbbb78 172.22.0.2:6379
slots:0-5460 (5461 slots) master
M: c91fa493fb3a135678887081608e460e23593e34 172.22.0.3:6379
slots:5461-10922 (5462 slots) master
M: d3d17e760fa04e2cd70897c2719aa9da9d9ddda5 172.22.0.4:6379
slots:10923-16383 (5461 slots) master
S: de9cee59f2736fdecbc7245420f13d5429a7d8d4 172.22.0.5:6379
replicates 508a55e8eb9caa4962c21ac6a5374ef15bfbbb78
S: 6815f22140c40b6a8acba5a865b97b12d94c9bdb 172.22.0.6:6379
replicates c91fa493fb3a135678887081608e460e23593e34
S: 4ece54218638ac07b9ce4b4911bcd19da0c75e7b 172.22.0.7:6379
replicates d3d17e760fa04e2cd70897c2719aa9da9d9ddda5
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 172.22.0.2:6379)
M: 508a55e8eb9caa4962c21ac6a5374ef15bfbbb78 172.22.0.2:6379
slots:0-5460 (5461 slots) master
M: c91fa493fb3a135678887081608e460e23593e34 172.22.0.3:6379
slots:5461-10922 (5462 slots) master
M: d3d17e760fa04e2cd70897c2719aa9da9d9ddda5 172.22.0.4:6379
slots:10923-16383 (5461 slots) master
M: de9cee59f2736fdecbc7245420f13d5429a7d8d4 172.22.0.5:6379
slots: (0 slots) master
replicates 508a55e8eb9caa4962c21ac6a5374ef15bfbbb78
M: 6815f22140c40b6a8acba5a865b97b12d94c9bdb 172.22.0.6:6379
slots: (0 slots) master
replicates c91fa493fb3a135678887081608e460e23593e34
M: 4ece54218638ac07b9ce4b4911bcd19da0c75e7b 172.22.0.7:6379
slots: (0 slots) master
replicates d3d17e760fa04e2cd70897c2719aa9da9d9ddda5
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
其中,在運行到 Can I set the above configuration? (type ‘yes’ to accept): 時,要輸入 yes 後才能繼續往下執行,執行完畢後,3主3從的redis cluster集羣就創建好了
四、使用Jedis連接redis cluster
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
/**
* @author chenjc
* @since 2020-01-08
*/
public class ClusterTest {
public static void main(String[] args) {
JedisCluster jedisCluster = new JedisCluster(new HostAndPort("localhost", 6395));
jedisCluster.set("debo", "666666");
System.out.println(jedisCluster.get("debo"));
}
}
連接redis cluster的時候,只需要連接集羣中的任一節點(不分主從),節點間會相互協調,通過 MOVED 和 ASK 等命令,自動定位到key實際應該存儲的節點。
只給Jedis配置一個節點地址是有潛在風險的,當這個節點本身掛掉了,那麼Jedis就失去了和整個redis cluster集羣的聯繫了,所以一般會將全部節點信息給到Jedis,代碼如下
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import java.util.HashSet;
import java.util.Set;
/**
* @author chenjc
* @since 2020-01-08
*/
public class ClusterTest {
public static void main(String[] args) {
Set<HostAndPort> nodes = new HashSet<>();
HostAndPort node1 = new HostAndPort("localhost", 6391);
HostAndPort node2 = new HostAndPort("localhost", 6392);
HostAndPort node3 = new HostAndPort("localhost", 6393);
HostAndPort node4 = new HostAndPort("localhost", 6394);
HostAndPort node5 = new HostAndPort("localhost", 6395);
HostAndPort node6 = new HostAndPort("localhost", 6396);
nodes.add(node1);
nodes.add(node2);
nodes.add(node3);
nodes.add(node4);
nodes.add(node5);
nodes.add(node6);
JedisCluster jedisCluster = new JedisCluster(nodes);
jedisCluster.set("debo", "666666");
System.out.println(jedisCluster.get("debo"));
}
}
也可以使用redis-cli -c -p 6391
命令在命令行連接集羣進行相關操作
redis cluster集羣在master節點下線的時候,會自動將slave節點升級爲master,所以redis cluster既支持分片又支持主從自動切換,相較sentinel只支持主從自動切換來說,功能更加強大了。