Redis哨兵高可用架构
sentinel哨兵是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点。
哨兵架构下client端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel代理访问redis的主节点,当redis的主节点发生变化,哨兵会第一时间感知到,并且将新的redis主节点通知给client端(这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息)
单机多个哨兵架构测试搭建步骤(可以直接忽略这个,一般不会在单机上部署多个哨兵,建议直接跳过看下面多机部署的):
1、复制一份sentinel.conf文件
cp sentinel.conf sentinel-26379.conf
2、将相关配置修改为如下值:
port 26379
daemonize yes
pidfile "/var/run/redis-sentinel-26379.pid"
logfile "26379.log"
dir "/usr/local/redis-5.0.3/data"
# sentinel monitor <master-redis-name> <master-redis-ip> <master-redis-port> <quorum>
# quorum是一个数字,指明当有多少个sentinel认为一个master失效时(值一般为:sentinel总数/2 + 1),master才算真正失效
sentinel monitor mymaster 192.168.0.60 6379 2 # mymaster这个名字随便取,客户端访问时会用到
3、启动sentinel哨兵实例
src/redis-sentinel sentinel-26379.conf
4、查看sentinel的info信息
src/redis-cli -p 26379
127.0.0.1:26379>info
可以看到Sentinel的info里已经识别出了redis的主从
5、可以自己再配置两个sentinel,端口26380和26381,注意上述配置文件里的对应数字都要修改
sentinel集群都启动完毕后,会将哨兵集群的元数据信息写入所有sentinel的配置文件里去(追加在文件的最下面),我们查看下如下配置文件sentinel-26379.conf,如下所示:
sentinel known-replica mymaster 192.168.0.60 6380 #代表redis主节点的从节点信息
sentinel known-replica mymaster 192.168.0.60 6381 #代表redis主节点的从节点信息
sentinel known-sentinel mymaster 192.168.0.60 26380 52d0a5d70c1f90475b4fc03b6ce7c3c56935760f #代表感知到的其它哨兵节点
sentinel known-sentinel mymaster 192.168.0.60 26381 e9f530d3882f8043f76ebb8e1686438ba8bd5ca6 #代表感知到的其它哨兵节点
当redis主节点如果挂了,哨兵集群会重新选举出新的redis主节点,同时会修改所有sentinel节点配置文件的集群元数据信息,比如6379的redis如果挂了,假设选举出的新主节点是6380,则sentinel文件里的集群元数据信息会变成如下所示:
sentinel known-replica mymaster 192.168.0.60 6379 #代表主节点的从节点信息
sentinel known-replica mymaster 192.168.0.60 6381 #代表主节点的从节点信息
sentinel known-sentinel mymaster 192.168.0.60 26380 52d0a5d70c1f90475b4fc03b6ce7c3c56935760f #代表感知到的其它哨兵节点
sentinel known-sentinel mymaster 192.168.0.60 26381 e9f530d3882f8043f76ebb8e1686438ba8bd5ca6 #代表感知到的其它哨兵节点
同时还会修改sentinel文件里之前配置的mymaster对应的6379端口,改为6380
sentinel monitor mymaster 192.168.0.60 6380 2
当6379的redis实例再次启动时,哨兵集群根据集群元数据信息就可以将6379端口的redis节点作为从节点加入集群。
下面是多机部署,线上三台云主机部署(redis一主二从),三台都先启动好redis,然后启动主redis的sentinel和从节点的sentinel,配置完全一样(注意myid不能一样,一样的话sentinel会互相感应不到)就可以了:
#关闭保护模式
protected-mode no
#默认端口
port 26379
#后台运行
daemonize yes
#默认设置
pidfile "/var/run/redis-sentinel.pid"
#log文件名称
logfile "sentinel.log"
#指定dir目录
dir "/usr/local/redis/bin/data"
#开启哨兵,三台机器都同时监听200这个主节点redis情况
sentinel monitor mymaster 192.168.0.200 6379 2
#三台都要设置一样的密码,这个是sentinel的连接密码,java客户端在使用连接池连接时用的
#注意这个非redis的密码,redis的连接密码在redis.conf的requirepass和masterauth里配置
sentinel auth-pass mymaster azhi2021888
查看sentinel.conf:
哨兵的Jedis连接代码:
引入相关依赖:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.6.3</version>
</dependency>
简单测试代码:
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
public class JedisSentinelTest {
public static void main(String[] args) throws IOException {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(10);
jedisPoolConfig.setMaxIdle(5);
jedisPoolConfig.setMinIdle(5);
System.out.println("start jedisSentinelTest...");
// 哨兵信息
Set<String> sentinels = new HashSet<>(Arrays.asList("124.71.115.203:26379",
"139.9.51.215:26379","124.71.7.195:26379"));
// 创建连接池
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels,jedisPoolConfig,"azhi2021888");
// 获取客户端
Jedis jedis = pool.getResource();
// 执行两个命令
jedis.set("mykey", "myvalue");
String value = jedis.get("mykey");
System.out.println(value);
}
}
demo代码本地运行的效果:
因为redis是在三台云主机上部署的,而sentinel配置里写的是三台云主机的内网主机ip地址,所以在本地会连接不上sentinel拿出来的这个192.168.0.200主机IP的。
一般线上redis都是不对开外放的,一般都只是开放api服务接口,让api服务接口在服务器上通过内部ip地址去访问redis。
如果是在开发阶段可以把sentinel.conf里的sentinel monitor mymaster ip port改为公网的地址和开放对应端口,又或者是在本地搭建redis开发集群测试环境,但要注意在线上就别配置公网地址和开放外部连接端口了。
demo代码发布到云主机服务器上运行的效果:
主redis:
从redis1:
从redis2:
可以看出写入正常,两个从节点同步数据也正常。
至此,关于redis的1主2从+哨兵集群的配置、代码连接使用已测试完毕。