Redis哨兵高可用架构
sentinel哨兵是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点。
哨兵架构下client端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel代理访问redis的主节点,当redis的主节点发生变化,哨兵会第一时间感知到,并且将新的redis主节点通知给client端(这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息)
单机多个哨兵架构测试搭建步骤(可以直接忽略这个,一般不会在单机上部署多个哨兵,建议直接跳过看下面多机部署的):
1、复制一份sentinel.conf文件cp sentinel.conf sentinel-26379.conf2、将相关配置修改为如下值:port 26379daemonize yespidfile "/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.conf4、查看sentinel的info信息src/redis-cli -p 26379127.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从+哨兵集群的配置、代码连接使用已测试完毕。
