Redis哨兵高可用架构
    image.png
    sentinel哨兵是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点。
    哨兵架构下client端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel代理访问redis的主节点,当redis的主节点发生变化,哨兵会第一时间感知到,并且将新的redis主节点通知给client端(这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息)
    单机多个哨兵架构测试搭建步骤(可以直接忽略这个,一般不会在单机上部署多个哨兵,建议直接跳过看下面多机部署的):

    1. 1、复制一份sentinel.conf文件
    2. cp sentinel.conf sentinel-26379.conf
    3. 2、将相关配置修改为如下值:
    4. port 26379
    5. daemonize yes
    6. pidfile "/var/run/redis-sentinel-26379.pid"
    7. logfile "26379.log"
    8. dir "/usr/local/redis-5.0.3/data"
    9. # sentinel monitor <master-redis-name> <master-redis-ip> <master-redis-port> <quorum>
    10. # quorum是一个数字,指明当有多少个sentinel认为一个master失效时(值一般为:sentinel总数/2 + 1),master才算真正失效
    11. sentinel monitor mymaster 192.168.0.60 6379 2 # mymaster这个名字随便取,客户端访问时会用到
    12. 3、启动sentinel哨兵实例
    13. src/redis-sentinel sentinel-26379.conf
    14. 4、查看sentinelinfo信息
    15. src/redis-cli -p 26379
    16. 127.0.0.1:26379>info
    17. 可以看到Sentinelinfo里已经识别出了redis的主从
    18. 5、可以自己再配置两个sentinel,端口2638026381,注意上述配置文件里的对应数字都要修改

    sentinel集群都启动完毕后,会将哨兵集群的元数据信息写入所有sentinel的配置文件里去(追加在文件的最下面),我们查看下如下配置文件sentinel-26379.conf,如下所示:

    1. sentinel known-replica mymaster 192.168.0.60 6380 #代表redis主节点的从节点信息
    2. sentinel known-replica mymaster 192.168.0.60 6381 #代表redis主节点的从节点信息
    3. sentinel known-sentinel mymaster 192.168.0.60 26380 52d0a5d70c1f90475b4fc03b6ce7c3c56935760f #代表感知到的其它哨兵节点
    4. sentinel known-sentinel mymaster 192.168.0.60 26381 e9f530d3882f8043f76ebb8e1686438ba8bd5ca6 #代表感知到的其它哨兵节点

    当redis主节点如果挂了,哨兵集群会重新选举出新的redis主节点,同时会修改所有sentinel节点配置文件的集群元数据信息,比如6379的redis如果挂了,假设选举出的新主节点是6380,则sentinel文件里的集群元数据信息会变成如下所示:

    1. sentinel known-replica mymaster 192.168.0.60 6379 #代表主节点的从节点信息
    2. sentinel known-replica mymaster 192.168.0.60 6381 #代表主节点的从节点信息
    3. sentinel known-sentinel mymaster 192.168.0.60 26380 52d0a5d70c1f90475b4fc03b6ce7c3c56935760f #代表感知到的其它哨兵节点
    4. sentinel known-sentinel mymaster 192.168.0.60 26381 e9f530d3882f8043f76ebb8e1686438ba8bd5ca6 #代表感知到的其它哨兵节点

    同时还会修改sentinel文件里之前配置的mymaster对应的6379端口,改为6380

    1. sentinel monitor mymaster 192.168.0.60 6380 2

    当6379的redis实例再次启动时,哨兵集群根据集群元数据信息就可以将6379端口的redis节点作为从节点加入集群。

    下面是多机部署,线上三台云主机部署(redis一主二从),三台都先启动好redis,然后启动主redis的sentinel和从节点的sentinel,配置完全一样(注意myid不能一样,一样的话sentinel会互相感应不到)就可以了:

    1. #关闭保护模式
    2. protected-mode no
    3. #默认端口
    4. port 26379
    5. #后台运行
    6. daemonize yes
    7. #默认设置
    8. pidfile "/var/run/redis-sentinel.pid"
    9. #log文件名称
    10. logfile "sentinel.log"
    11. #指定dir目录
    12. dir "/usr/local/redis/bin/data"
    13. #开启哨兵,三台机器都同时监听200这个主节点redis情况
    14. sentinel monitor mymaster 192.168.0.200 6379 2
    15. #三台都要设置一样的密码,这个是sentinel的连接密码,java客户端在使用连接池连接时用的
    16. #注意这个非redis的密码,redis的连接密码在redis.conf的requirepass和masterauth里配置
    17. sentinel auth-pass mymaster azhi2021888

    查看sentinel.conf:
    image.png
    哨兵的Jedis连接代码:
    引入相关依赖:

    1. <dependency>
    2. <groupId>redis.clients</groupId>
    3. <artifactId>jedis</artifactId>
    4. <version>3.6.3</version>
    5. </dependency>

    简单测试代码:

    1. import java.io.IOException;
    2. import java.util.Arrays;
    3. import java.util.HashSet;
    4. import java.util.Set;
    5. import redis.clients.jedis.Jedis;
    6. import redis.clients.jedis.JedisPoolConfig;
    7. import redis.clients.jedis.JedisSentinelPool;
    8. public class JedisSentinelTest {
    9. public static void main(String[] args) throws IOException {
    10. JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
    11. jedisPoolConfig.setMaxTotal(10);
    12. jedisPoolConfig.setMaxIdle(5);
    13. jedisPoolConfig.setMinIdle(5);
    14. System.out.println("start jedisSentinelTest...");
    15. // 哨兵信息
    16. Set<String> sentinels = new HashSet<>(Arrays.asList("124.71.115.203:26379",
    17. "139.9.51.215:26379","124.71.7.195:26379"));
    18. // 创建连接池
    19. JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels,jedisPoolConfig,"azhi2021888");
    20. // 获取客户端
    21. Jedis jedis = pool.getResource();
    22. // 执行两个命令
    23. jedis.set("mykey", "myvalue");
    24. String value = jedis.get("mykey");
    25. System.out.println(value);
    26. }
    27. }

    demo代码本地运行的效果:
    image.png
    因为redis是在三台云主机上部署的,而sentinel配置里写的是三台云主机的内网主机ip地址,所以在本地会连接不上sentinel拿出来的这个192.168.0.200主机IP的。
    一般线上redis都是不对开外放的,一般都只是开放api服务接口,让api服务接口在服务器上通过内部ip地址去访问redis。
    如果是在开发阶段可以把sentinel.conf里的sentinel monitor mymaster ip port改为公网的地址和开放对应端口,又或者是在本地搭建redis开发集群测试环境,但要注意在线上就别配置公网地址和开放外部连接端口了。
    demo代码发布到云主机服务器上运行的效果:
    image.png
    主redis:
    image.png
    从redis1:
    image.png
    从redis2:
    image.png
    可以看出写入正常,两个从节点同步数据也正常。
    至此,关于redis的1主2从+哨兵集群的配置、代码连接使用已测试完毕。