一、準備工作
需要先創建一個docker網絡,類型爲橋接網絡,後面會將redis主從節點和sentinel集羣都加入到這網絡中,目的是保證全部節點的相互連通。
# 創建名稱爲redis-net的橋接網絡
docker network create -d bridge redis-net
注:其實可以不用特意創建一個網絡,默認所有節點會自動加入到名稱爲bridge的橋接網絡中,這個網絡是默認已存在的
二、部署redis節點
- 在自己電腦上建一個文件夾,然後放一個redis-6380.conf配置文件,這個配置文件直接拷貝的默認的redis.conf配置文件(實不相瞞,我就是用的redis官網的redis4.0.14配置文件),只需修改如下兩個配置:
#bind 127.0.0.1
protected-mode no
- 在命令行運行以下命令,用來在docker容器中啓動一個redis節點
docker run -d -p 6380:6379 --name redis-node-6380 --network redis-net --mount type=bind,source=/home/debo/dockerData/redis/redis-6380.conf,target=/etc/redis.conf redis:4.0.14 redis-server /etc/redis.conf
-d
表示在後臺運行-p 6380:6379
表示將容器中的6379端口綁定到宿主機的6380端口,這樣就可以在容器外部使用localhost:6380訪問這個redis--name redis-node-6380
表示容器名稱是redis-node-6380--network redis-net
表示加入redis-net網絡--mount type=bind,source=/home/debo/dockerData/redis/redis-6380.conf,target=/etc/redis.conf
表示將宿主機的redis-6380.conf文件掛載到容器中/etc/redis.conf下redis:4.0.14 redis-server /etc/redis.conf
表示使用鏡像redis:4.0.14啓動容器,如果沒有這鏡像,會自動從鏡像倉庫下載的,同時啓動成功後執行redis-server命令並使用容器中的/etc/redis.conf作爲配置文件
- 將redis-6380.conf文件複製兩份,分別重命名爲redis-6381.conf和redis-6382.conf,然後依次執行如下命令,完成另外兩個redis節點的部署
docker run -d -p 6381:6379 --name redis-node-6381 --network redis-net --mount type=bind,source=/home/debo/dockerData/redis/redis-6381.conf,target=/etc/redis.conf redis:4.0.14 redis-server /etc/redis.conf
docker run -d -p 6382:6379 --name redis-node-6382 --network redis-net --mount type=bind,source=/home/debo/dockerData/redis/redis-6382.conf,target=/etc/redis.conf redis:4.0.14 redis-server /etc/redis.conf
以上操作完成後,就將3個獨立的redis節點部署完成了。可以在宿主機(也就是自己電腦)命令行中執行命令redis-cli -p 6380
看看是否部署成功
三、設置redis主從複製
以redis-node-6380作爲主節點,redis-node-6381和redis-node-6382作爲從節點,實現一主兩從架構。
- 運行命令
docker network inspect redis-net
會輸出如下信息
"Containers": {
"1411e74f1619f6d4268fc0f9f70f89d9ba211729db49906cbc568d9f10c41ddc": {
"Name": "redis-node-6382",
"EndpointID": "0e3429f73ade0a9b972cf90fb5b4d299914cbafb1788f4c72aa00e6cf16a536f",
"MacAddress": "02:42:ac:12:00:04",
"IPv4Address": "172.18.0.4/16",
"IPv6Address": ""
},
"74dbf13733caab38979141899dad954a3b64e9674b78e1378160cbdea203343f": {
"Name": "redis-node-6381",
"EndpointID": "c87bc4327a7fc471339ce04d465133745c460a70304854d33ec760df8e7ad7c6",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
},
"9e1230cfc3a79f7dfe01397f1f473a4d2809c7ebe909267fd7edd45472641c19": {
"Name": "redis-node-6380",
"EndpointID": "5121006f5c432723d764cf9b8a06b8db11b7f10d643a28ef9be0c48e959ea592",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
}
可見redis-node-6380節點的IP地址爲172.18.0.2
2. 修改redis-6381.conf和redis-6382.conf,設置從節點,要修改的配置如下:
slaveof 172.18.0.2 6379
- 重啓redis-node-6381和redis-node-6382兩個容器
docker restart redis-node-6381
docker restart redis-node-6382
完成以上步驟後,一主兩從的redis高可用架構就部署好了,但是當主節點掛掉以後,從節點提升爲主節點這動作不是自動完成的,需要我們手動去將其中一個從節點提升爲主節點,同時還需要修改調用方的主節點地址,這個太麻煩了,所以我們需要sentinel集羣,它可以在主節點掛掉以後自動將其中一個從節點提升爲主節點,當主節點恢復以後,自動將老的主節點設置爲新主節點的從節點,同時主節點地址對調用方透明。
四、部署sentinel集羣
- 在自己電腦上建一個文件夾,然後放一個sentinel-26380.conf配置文件,這個配置文件直接拷貝的默認的sentinel.conf配置文件,只需修改如下兩個配置:
protected-mode no
sentinel monitor mymaster 172.18.0.2 6379 2
- 在命令行運行以下命令,用來在docker容器中啓動一個sentinel節點
docker run -d -p 26380:26379 --name sentinel-node-26380 --network redis-net --mount type=bind,source=/home/debo/dockerData/redis/sentinel-26380.conf,target=/etc/sentinel.conf redis:4.0.14 redis-sentinel /etc/sentinel.conf
- 將sentinel-26380.conf文件複製兩份,分別重命名爲sentinel-26381.conf和sentinel-26382.conf,然後依次執行如下命令,完成另外兩個sentinel節點的部署
docker run -d -p 26381:26379 --name sentinel-node-26381 --network redis-net --mount type=bind,source=/home/debo/dockerData/redis/sentinel-26381.conf,target=/etc/sentinel.conf redis:4.0.14 redis-sentinel /etc/sentinel.conf
docker run -d -p 26382:26379 --name sentinel-node-26382 --network redis-net --mount type=bind,source=/home/debo/dockerData/redis/sentinel-26382.conf,target=/etc/sentinel.conf redis:4.0.14 redis-sentinel /etc/sentinel.conf
以上操作完成後,含有三個節點的sentinel集羣就部署完成了
五、使用Jedis連接sentinel集羣進行驗證
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.Set;
/**
* @author debo
* @date 2020-01-03
*/
public class SentinelTest {
public static void main(String[] args) {
String masterName = "mymaster";
// sentinel地址集合
Set<String> addresses = new HashSet<>();
addresses.add("localhost:26380");
addresses.add("localhost:26381");
addresses.add("localhost:26382");
JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName, addresses);
Jedis jedis = jedisSentinelPool.getResource();
jedis.set("testkey", "123321");
System.out.println();
}
}
可以發現,每次的jedis使用的都是主節點,當我們將主節點容器停止後,過一會兒再運行這例子,發現jedis使用的是新的主節點。(JedisSentinelPool中每次拿到的都是主節點連接,無法拿到從節點連接,如果要拿從節點信息,可以自己擴展)
六、sentinel集羣監控多組redis主從節點
sentinel集羣可以監控多組redis主從節點,假設現在要增加監控另一組redis主從節點,只需要將另一組的redis主節點信息添加到sentinel配置文件中即可,如:
sentinel monitor mymaster 172.18.0.2 6379 2
sentinel monitor mymaster1 172.18.0.5 6379 2
相應地,業務代碼中如果要同時使用兩組主從節點,那麼代碼可以調整如下:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.Set;
/**
* @author debo
* @date 2020-01-03
*/
public class SentinelTest {
public static void main(String[] args) {
String masterName = "mymaster";
String master1Name = "mymaster1";
// sentinel地址集合
Set<String> addresses = new HashSet<>();
addresses.add("localhost:26380");
addresses.add("localhost:26381");
addresses.add("localhost:26382");
// 監控第一組redis主從節點
JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName, addresses);
Jedis jedis = jedisSentinelPool.getResource();
jedis.set("first", "123321");
System.out.println();
// 監控第二組redis主從節點
JedisSentinelPool jedisSentinelPool1 = new JedisSentinelPool(master1Name, addresses);
Jedis jedis1 = jedisSentinelPool1.getResource();
jedis1.set("second", "123321");
System.out.println();
}
}
需要說明的是,受sentinel集羣監控的這兩組redis主從節點是相互獨立的,互不影響(不同於redis分片集羣)。