Redis-19Redis哨兵Sentinel模式-Centos6.5上3台主机1主2从3哨兵的配置及通过代码访问哨兵

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis-19Redis哨兵Sentinel模式-Centos6.5上3台主机1主2从3哨兵的配置及通过代码访问哨兵

概述



Redis主从模式当主服务器右机后,需要手动把一台从服务器切换为主从服务器,这就需要人工干预,既费时费力,会造成一段时间内服务不可用,不推荐使用。 可以使用哨兵模式或者集群模式。 这里我们来探讨哨兵模式。


Redis 可以存在多台服务器,并且实现了主从复制的功能。哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立 的进程,作为进程,它会独立运行。原理是哨兵通过发送命令, 等待 Redis 服务器响应,从而监控运行的多个 Redis 实例。


这里哨兵有两个作用


通过发送命令,让 Redis 服务器返回监测其运行状态,包括主服务器和从服务器。

当 哨兵监测到 master宕机, 会自动将 slave 切换成 master,然后通过发布订阅模式通知到其他的从服务器,修改配置文件,让它们切换主机 。

只是现实中一个哨兵进程对 Redis 服务器进行监控,也可能出现问题,为了处理这个问题,还可以使用多个哨兵的监控,而各个哨兵之间还会相互监控,这样就变为了多个哨兵模式。多个哨兵不仅监控各个 Redis 服务器,而且哨兵之间互相监控 , 看看哨兵们是否还“活 ” 着。 如下图


20180929165937332.png


故障切换( failover)的过程:


假设主服务器岩机,哨兵 1 先监测到这个结果,当时系统并不会马上进行 failover 操作 ,而仅仅是哨兵1 主观地认为主机己经不可用,这个现象被称为主观下线。【SDOWN】

当后面的哨兵监测也监测到了主服务器不可用 , 并且有了 一定数量的哨兵认为主服务器不可用,那么哨兵之间就会形成一次投票,投票的结果由一个哨兵发起,进行 failover 操作,在 failover 操作的过程中切换成功后,就会通过发布订阅方式,让各个哨兵把自己监控的服务器实现切换主机 , 这个过程被称为客观下线【ODOWN】

这样对于客户端而言, 一切都是透明的 。


环境


redis版本: 4.0.11

操作系统: Centos6.5

主机信息 :


image.png


Sentinel环境搭建


如果没有足够的主机,那我们就通过VMware来搭建多个主机模拟下集群环境

参考我博文 VMware-使用VMware在本地搭建多个CentOS虚机

2018092917231331.png


同时需要在3台主机上部署Redis,参考我博 Redis-02Redis在linux下的安装及常见问题

20180929172328383.png


完成上面两步之后 ,就可以着手调整部署了


防火墙策略的调整

确保redis和哨兵进程的端口,在防火墙上开放。


redis的默认6379端口,在防火墙上开放,可以在本地通过RedisDeskTopManager来登录

哨兵的默认26379端口,在防火墙上开放,确保哨兵之间的通信。


这里为了方便起见,选择了关闭防火墙。


CentOS6.5永久关闭防火墙


使用root用户


[root@artisan ~]# service iptables stop
[root@artisan ~]# service iptables status
iptables: Firewall is not running
[root@artisan ~]# chkconfig iptables off
[root@artisan ~]# 

配置修改【最少修改】 (Redis集群带访问密码)

这里说的是Redis集群配置了访问密码的场景。

Redis 的主服务器的配置修改

登录192.168.31.66主机


仅说需要调整的地方,未说明的地方保持默认即可。

#使得 Redis 服务器可以跨网络访问
bind  0.0.0.0
#设置密码
requirepass  artisan
#主服务器密码
masterauth  artisan

因为发生切换时预先设定的master会变成slave,下次再发生故障的时候,如果没有masterauth artisan会失败。

为了方便观察日志,我们这里 daemonize no 暂时没有修改。


Redis 的从服务器的配置修改

#使得 Redis 服务器可以跨网络访问
bind  0.0.0.0
#设置密码
requirepass  artisan
#指定主服务器,注意:有关 slaveof 的配置只是配置从服务器,而主服务器不需要配置
slaveof 192.168.31.56 637
#主服务器密码 , 注意:有关 slaveof 的配置只是配置从服务器,而主服务器不需要配置
masterauth  artisan


上述内容主要是配置 Redis 服务器,从服务器比主服务器多一个 slaveof 的配置和密码 ,这里配置的 bind 使得 Redis 服务器可以跨网段访问 。 而对于外部的访问还需要提供密码,因此还提供了 requirepass 的配置,用以配置密码 ,这样就配置完了 3 台服务器 。


哨兵sentinel.conf 的配置


配置 3 个哨 兵 , 每一个哨兵的配置都是一样的 ,在 Redis 安装目录下可以找到sentinel.conf 文件,然后对其进行修改

下面对 3 个哨兵的这个文件作出修改,同样也是在原有的基础上进行修改,仅仅列出改动的地方,如下所示

# 禁止保护模式
protected-mode no
# 配置监听的主服务器,这里 sentinel monitor 代表监控 ,
# mymaster 代表服务器名称,可以自定义
# 192.168.31.66 代表监控的主服务器
# 6379 代表端口
# 2 代表只有两个或者两个以上的哨兵认为主服务器不可用的时候,才会做故障切换操作
sentinel monitor mymaster 192.168.31.66  6379 2
# sentinel auth-pass 定义服务的密码
# mymaster 服务名称
# artisan Redis 服务器密码
sentinel auth-pass mymaster artisan 


关闭了保护模式,以便测试。 sentinel monitor 是配置一个哨兵主要的内 容 , 首先是自定义服务名称 mymaster,然后映射服务器和端口 。最后的 2 是代表当存在两个或者两个以上的哨兵投票认可当前主服务器不可用后 ,才会进行故障切换,这样可以降低因出错而切换主服务器的概率。 sentinel auth-pass 用于配置服务名称及其密码。


启动顺序


首先是主机 192.168.31.66的 Redis 服务进程 ,然后启动从机的服务进程,最后启动 3 个哨兵的服务进程

哨兵进程启动命令,指定配置文件

./redis-sentinel  ../etc/sentinel.conf


测试


写这篇博客的时候,已经模拟过一次主节点故障了,主节点已经被为了 192.168.31.56了 . 所以接着这里继续来看下。


首先启动 Redis主服务器的Redis服务 – > Redis从服务器的Redis服务(2个)。


然后启动 每台主机上对应的哨兵进程


56主机

[redis@artisan bin]$ ./redis-sentinel ../etc/sentinel.conf 
2128:X 30 Sep 02:07:23.601 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
2128:X 30 Sep 02:07:23.602 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=2128, just started
2128:X 30 Sep 02:07:23.602 # Configuration loaded
2128:X 30 Sep 02:07:23.607 * Increased maximum number of open files to 4096 (it was originally set to 1024).
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 4.0.11 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in sentinel mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
 |    `-._   `._    /     _.-'    |     PID: 2128
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               
2128:X 30 Sep 02:07:23.611 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
2128:X 30 Sep 02:07:23.611 # Sentinel ID is db0d6183683b97f001514c53e36ceabd2bcf2bb4
2128:X 30 Sep 02:07:23.611 # +monitor master mymaster 192.168.31.56 6379 quorum 2

66主机

[redis@artisan bin]$ ./redis-sentinel ../etc/sentinel.conf 
2696:X 30 Sep 02:06:52.261 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
2696:X 30 Sep 02:06:52.261 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=2696, just started
2696:X 30 Sep 02:06:52.261 # Configuration loaded
2696:X 30 Sep 02:06:52.262 * Increased maximum number of open files to 4096 (it was originally set to 1024).
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 4.0.11 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in sentinel mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
 |    `-._   `._    /     _.-'    |     PID: 2696
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               
2696:X 30 Sep 02:06:52.269 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
2696:X 30 Sep 02:06:52.269 # Sentinel ID is 06f62ff2d7739c81c83bbca1864a6765ca67ab36
2696:X 30 Sep 02:06:52.269 # +monitor master mymaster 192.168.31.56 6379 quorum 2


176主机

[redis@artisan ~]$ cd redis/redis-4.0.11/bin/
[redis@artisan bin]$ ./redis-sentinel ../etc/sentinel.conf 
2211:X 30 Sep 02:07:44.182 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
2211:X 30 Sep 02:07:44.182 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=2211, just started
2211:X 30 Sep 02:07:44.182 # Configuration loaded
2211:X 30 Sep 02:07:44.183 * Increased maximum number of open files to 4096 (it was originally set to 1024).
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 4.0.11 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in sentinel mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
 |    `-._   `._    /     _.-'    |     PID: 2211
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               
2211:X 30 Sep 02:07:44.188 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
2211:X 30 Sep 02:07:44.188 # Sentinel ID is e95574e02478706f3cd27b8022340523d3a09e6d
2211:X 30 Sep 02:07:44.188 # +monitor master mymaster 192.168.31.56 6379 quorum 2


然后停掉Master 56的redis-server进程,观察哨兵日志的选举

56的哨兵输出

2128:X 30 Sep 02:09:37.657 # +sdown master mymaster 192.168.31.56 6379
2128:X 30 Sep 02:09:37.709 # +odown master mymaster 192.168.31.56 6379 #quorum 3/2
2128:X 30 Sep 02:09:37.710 # +new-epoch 2
2128:X 30 Sep 02:09:37.710 # +try-failover master mymaster 192.168.31.56 6379
2128:X 30 Sep 02:09:37.721 # +vote-for-leader db0d6183683b97f001514c53e36ceabd2bcf2bb4 2
2128:X 30 Sep 02:09:37.730 # e95574e02478706f3cd27b8022340523d3a09e6d voted for db0d6183683b97f001514c53e36ceabd2bcf2bb4 2
2128:X 30 Sep 02:09:37.746 # 06f62ff2d7739c81c83bbca1864a6765ca67ab36 voted for db0d6183683b97f001514c53e36ceabd2bcf2bb4 2
2128:X 30 Sep 02:09:37.777 # +elected-leader master mymaster 192.168.31.56 6379
2128:X 30 Sep 02:09:37.777 # +failover-state-select-slave master mymaster 192.168.31.56 6379
2128:X 30 Sep 02:09:37.861 # +selected-slave slave 192.168.31.176:6379 192.168.31.176 6379 @ mymaster 192.168.31.56 6379
2128:X 30 Sep 02:09:37.861 * +failover-state-send-slaveof-noone slave 192.168.31.176:6379 192.168.31.176 6379 @ mymaster 192.168.31.56 6379
2128:X 30 Sep 02:09:37.961 * +failover-state-wait-promotion slave 192.168.31.176:6379 192.168.31.176 6379 @ mymaster 192.168.31.56 6379
2128:X 30 Sep 02:09:38.822 # +promoted-slave slave 192.168.31.176:6379 192.168.31.176 6379 @ mymaster 192.168.31.56 6379
2128:X 30 Sep 02:09:38.822 # +failover-state-reconf-slaves master mymaster 192.168.31.56 6379
2128:X 30 Sep 02:09:38.879 * +slave-reconf-sent slave 192.168.31.66:6379 192.168.31.66 6379 @ mymaster 192.168.31.56 6379
2128:X 30 Sep 02:09:39.817 * +slave-reconf-inprog slave 192.168.31.66:6379 192.168.31.66 6379 @ mymaster 192.168.31.56 6379
2128:X 30 Sep 02:09:39.818 * +slave-reconf-done slave 192.168.31.66:6379 192.168.31.66 6379 @ mymaster 192.168.31.56 6379
2128:X 30 Sep 02:09:39.891 # -odown master mymaster 192.168.31.56 6379
2128:X 30 Sep 02:09:39.891 # +failover-end master mymaster 192.168.31.56 6379
2128:X 30 Sep 02:09:39.891 # +switch-master mymaster 192.168.31.56 6379 192.168.31.176 6379
2128:X 30 Sep 02:09:39.894 * +slave slave 192.168.31.66:6379 192.168.31.66 6379 @ mymaster 192.168.31.176 6379
2128:X 30 Sep 02:09:39.895 * +slave slave 192.168.31.56:6379 192.168.31.56 6379 @ mymaster 192.168.31.176 6379
2128:X 30 Sep 02:10:09.920 # +sdown slave 192.168.31.56:6379 192.168.31.56 6379 @ mymaster 192.168.31.176 6379


+sdown 表示哨兵主观认为数据库下线

+odown 表示哨兵客观认为数据库下线

+try-failover 表示哨兵开始进行故障恢复

+failover-end 表示哨兵完成故障修复,其中包括了领头哨兵的选举、备选从数据库的选择等等较为复杂的过程

+switch-master表示主数据库从56服务器迁移到176服务器

+slave列出了新的主数据库的2个从数据库,而哨兵并没有彻底清除56服务器的实力信息,这是因为停止的实例有可能会在将来恢复,哨兵会让其重新加入进来


66的哨兵输入

2696:X 30 Sep 02:09:21.731 # +sdown master mymaster 192.168.31.56 6379
2696:X 30 Sep 02:09:21.848 # +new-epoch 2
2696:X 30 Sep 02:09:21.853 # +vote-for-leader db0d6183683b97f001514c53e36ceabd2bcf2bb4 2
2696:X 30 Sep 02:09:22.838 # +odown master mymaster 192.168.31.56 6379 #quorum 3/2
2696:X 30 Sep 02:09:22.838 # Next failover delay: I will not start a failover before Sun Sep 30 02:15:22 2018
2696:X 30 Sep 02:09:22.990 # +config-update-from sentinel db0d6183683b97f001514c53e36ceabd2bcf2bb4 192.168.31.56 26379 @ mymaster 192.168.31.56 6379
2696:X 30 Sep 02:09:22.990 # +switch-master mymaster 192.168.31.56 6379 192.168.31.176 6379
2696:X 30 Sep 02:09:22.993 * +slave slave 192.168.31.66:6379 192.168.31.66 6379 @ mymaster 192.168.31.176 6379
2696:X 30 Sep 02:09:22.993 * +slave slave 192.168.31.56:6379 192.168.31.56 6379 @ mymaster 192.168.31.176 6379
2696:X 30 Sep 02:09:53.008 # +sdown slave 192.168.31.56:6379 192.168.31.56 6379 @ mymaster 192.168.31.176 6379

176的哨兵输出

2211:X 30 Sep 02:09:45.243 # +sdown master mymaster 192.168.31.56 6379
2211:X 30 Sep 02:09:45.336 # +new-epoch 2
2211:X 30 Sep 02:09:45.339 # +vote-for-leader db0d6183683b97f001514c53e36ceabd2bcf2bb4 2
2211:X 30 Sep 02:09:45.341 # +odown master mymaster 192.168.31.56 6379 #quorum 2/2
2211:X 30 Sep 02:09:45.341 # Next failover delay: I will not start a failover before Sun Sep 30 02:15:45 2018
2211:X 30 Sep 02:09:46.492 # +config-update-from sentinel db0d6183683b97f001514c53e36ceabd2bcf2bb4 192.168.31.56 26379 @ mymaster 192.168.31.56 6379
2211:X 30 Sep 02:09:46.492 # +switch-master mymaster 192.168.31.56 6379 192.168.31.176 6379
2211:X 30 Sep 02:09:46.493 * +slave slave 192.168.31.66:6379 192.168.31.66 6379 @ mymaster 192.168.31.176 6379
2211:X 30 Sep 02:09:46.494 * +slave slave 192.168.31.56:6379 192.168.31.56 6379 @ mymaster 192.168.31.176 6379
2211:X 30 Sep 02:10:16.557 # +sdown slave 192.168.31.56:6379 192.168.31.56 6379 @ mymaster 192.168.31.176 6379

结果是选举了 176作为Master

通过客户端也可以看到176的role为master


20180929183527594.png


使用JavaAPI 访问 Redis Sentinel集群


我们先把停掉的56起来,现在master是176主机,56起来之后,肯定是slave状态了。


20180929183857376.png


为了测试数据的干净,我们现在master节点上flushdb清空keys,redis会自动同步到到另外两个slave节点。


如果在slave机器上执行flushdb,会抛出如下异常

"READONLY You can't write against a read only slave."


在 Java 中使用哨兵模式 ,加入关于哨兵的信息即可,非常简单,如下

package com.artisan.redis.sentinel;
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 JavaRedisSentinel {
  public static void main(String[] args) {
    // 连接池配置
    JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
    jedisPoolConfig.setMaxIdle(50);
    jedisPoolConfig.setMaxTotal(100);
    jedisPoolConfig.setMaxWaitMillis(2000);
    // 哨兵信息
    Set<String> sentinelsSet = new HashSet<String>(Arrays.asList("192.168.31.66:26379", "192.168.31.56:26379", "192.168.31.176:26379"));
    // 创建连接池
    JedisSentinelPool sentinelPool = new JedisSentinelPool("mymaster", sentinelsSet, jedisPoolConfig, "artisan");
    // 获取客户端
    Jedis jedis = sentinelPool.getResource();
    // 执行指令测试下
    jedis.set("artisan_key", "artisan_value");
    String result = jedis.get("artisan_key");
    System.out.println("artisan_key对应的value为:" + result);
  }
}


运行:

九月 29, 2018 6:42:10 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Trying to find master from available Sentinels...
九月 29, 2018 6:42:10 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Redis master running at 192.168.31.176:6379, starting Sentinel listeners...
九月 29, 2018 6:42:10 下午 redis.clients.jedis.JedisSentinelPool initPool
信息: Created JedisPool to master at 192.168.31.176:6379
artisan_key对应的value为:artisan_value



划重点:Redis master running at 192.168.31.176:6379

去redis中查看,三个节点中均存在这个key

20180929184320812.png


20180929184328586.png

20180929184337604.png


停掉master的redis-server ,然后再次操作


为了验证哨兵的作用,我们可以把主机上的 Redis 服务器关闭 , 马上运行,你

就可以发现报错 , 那倒不是因为哨兵失效导致的,而是因为 Redis 哨兵默认超时 3 分钟后才会进行投票切换主机,等超过 3 分钟后再进行测试


输出

九月 29, 2018 6:45:05 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Trying to find master from available Sentinels...
九月 29, 2018 6:45:05 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Redis master running at 192.168.31.56:6379, starting Sentinel listeners...
九月 29, 2018 6:45:05 下午 redis.clients.jedis.JedisSentinelPool initPool
信息: Created JedisPool to master at 192.168.31.56:6379
artisan_key对应的value为:artisan_value

划重点: Redis master running at 192.168.31.56:6379


从日志可以看到 , 我们实际使用的是 192.168.31.56 服务器,这是因为在192.168.31.176服务器不可用后 , 哨兵经过投票切换为 192.168.31.56服务器,通过这样的自动切换就保证服务持续稳定运行了。


使用Spring访问Redis Sentinel集群

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder location="classpath:redis/redis.properties" />
    <!--2,注意新版本2.3以后,JedisPoolConfig的property name,不是maxActive而是maxTotal,而且没有maxWait属性,建议看一下Jedis源码或百度。 -->
    <!-- redis连接池配置 -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!--最大空闲数 -->
        <property name="maxIdle" value="${redis.maxIdle}" />
        <!--连接池的最大数据库连接数 -->
        <property name="maxTotal" value="${redis.maxTotal}" />
        <!--最大建立连接等待时间 -->
        <property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
        <!--逐出连接的最小空闲时间 默认1800000毫秒(30分钟) -->
        <property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}" />
        <!--每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3 -->
        <property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}" />
        <!--逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1 -->
        <property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}" />
      <property name="testOnBorrow" value="true"></property>
    <property name="testOnReturn" value="true"></property>
    <property name="testWhileIdle" value="true"></property>
    </bean>
  <!-- 键值序列化器设置为String 类型 -->
  <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
  <!-- jdk序列化器,可保存对象 -->
  <bean id="jdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
  <!-- 哨兵配置 -->
  <bean id="sentinelConfig" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
    <!-- 服务名称 -->
    <property name="master">
      <bean class="org.springframework.data.redis.connection.RedisNode">
        <property name="name" value="mymaster"/>
      </bean>
    </property>
    <!-- 哨兵服务 IP 和端口  -->
    <property name="sentinels">
      <set>
        <bean class="org.springframework.data.redis.connection.RedisNode">
          <constructor-arg name="host" value="192.168.31.56"/>
          <constructor-arg name="port" value="26379"/>
        </bean>
        <bean class="org.springframework.data.redis.connection.RedisNode">
          <constructor-arg name="host" value="192.168.31.66"/>
          <constructor-arg name="port" value="26379"/>
        </bean>
        <bean class="org.springframework.data.redis.connection.RedisNode">
          <constructor-arg name="host" value="192.168.31.176"/>
          <constructor-arg name="port" value="26379"/>
        </bean>
      </set>
    </property>
  </bean>
  <!--redis连接工厂 -->
    <bean id="jedisConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
        destroy-method="destroy">
        <constructor-arg name="sentinelConfig" ref="sentinelConfig"/>
        <constructor-arg name="poolConfig" ref="jedisPoolConfig"/>
        <property name="password" value="artisan"/>
    </bean>
  <!-- redis template definition -->
  <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
    p:connection-factory-ref="jedisConnectionFactory"
    p:keySerializer-ref="stringRedisSerializer"
    p:defaultSerializer-ref="stringRedisSerializer"
    p:valueSerializer-ref="jdkSerializationRedisSerializer">
  </bean>
</beans>
package com.artisan.redis.sentinel;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
public class SpringRedisSentinel {
  @SuppressWarnings({ "unchecked", "rawtypes", "resource" })
  public static void main(String[] args) {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:spring/spring-redis-sentinel.xml");
    RedisTemplate redisTemplate = ctx.getBean(RedisTemplate.class);
    String retVaule = (String) redisTemplate.execute((RedisOperations ops) -> {
      ops.boundValueOps("artisan_k").set("artisan_v");
      String value = (String) ops.boundValueOps("artisan_k").get();
      return value;
    });
    System.out.println(retVaule);
  }
}

先把停掉的176起来,确保集群正常 .执行应用程序

INFO : org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@73a8dfcc: startup date [Sat Sep 29 19:13:09 CST 2018]; root of context hierarchy
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [spring/spring-redis-sentinel.xml]
九月 29, 2018 7:13:09 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Trying to find master from available Sentinels...
九月 29, 2018 7:13:10 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Redis master running at 192.168.31.56:6379, starting Sentinel listeners...
九月 29, 2018 7:13:10 下午 redis.clients.jedis.JedisSentinelPool initPool
信息: Created JedisPool to master at 192.168.31.56:6379
artisan_v


Redis master running at 192.168.31.56:6379

停掉56 ,马上访问

INFO : org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@73a8dfcc: startup date [Sat Sep 29 19:15:27 CST 2018]; root of context hierarchy
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [spring/spring-redis-sentinel.xml]
九月 29, 2018 7:15:28 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Trying to find master from available Sentinels...
九月 29, 2018 7:15:28 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Redis master running at 192.168.31.56:6379, starting Sentinel listeners...
九月 29, 2018 7:15:28 下午 redis.clients.jedis.JedisSentinelPool initPool
信息: Created JedisPool to master at 192.168.31.56:6379
Exception in thread "main" org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
  at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:286)
  at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.getConnection(JedisConnectionFactory.java:469)
  at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:132)
  at org.springframework.data.redis.core.RedisConnectionUtils.bindConnection(RedisConnectionUtils.java:70)
  at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:250)
  at com.artisan.redis.sentinel.SpringRedisSentinel.main(SpringRedisSentinel.java:15)
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
  at redis.clients.util.Pool.getResource(Pool.java:53)
  at redis.clients.jedis.JedisSentinelPool.getResource(JedisSentinelPool.java:209)
  at redis.clients.jedis.JedisSentinelPool.getResource(JedisSentinelPool.java:17)
  at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:276)
  ... 5 more
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.ConnectException: Connection refused: connect
  at redis.clients.jedis.Connection.connect(Connection.java:207)
  at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:93)
  at redis.clients.jedis.BinaryJedis.connect(BinaryJedis.java:1767)
  at redis.clients.jedis.JedisFactory.makeObject(JedisFactory.java:106)
  at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:868)
  at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:435)
  at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363)
  at redis.clients.util.Pool.getResource(Pool.java:49)
  ... 8 more
Caused by: java.net.ConnectException: Connection refused: connect
  at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
  at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
  at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
  at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
  at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
  at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
  at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
  at java.net.Socket.connect(Socket.java:589)
  at redis.clients.jedis.Connection.connect(Connection.java:184)
  ... 15 more


等集群选举完后,再次访问

INFO : org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@73a8dfcc: startup date [Sat Sep 29 19:16:02 CST 2018]; root of context hierarchy
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [spring/spring-redis-sentinel.xml]
九月 29, 2018 7:16:03 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Trying to find master from available Sentinels...
九月 29, 2018 7:16:03 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Redis master running at 192.168.31.176:6379, starting Sentinel listeners...
九月 29, 2018 7:16:03 下午 redis.clients.jedis.JedisSentinelPool initPool
信息: Created JedisPool to master at 192.168.31.176:6379
artisan_v



Redis master running at 192.168.31.176:6379

切换到了176,确保了服务的可用。


哨兵模式的其他配置顶


image.png


sentinel down-after-milliseconds 配置项只是一个哨兵在超过其指定的毫秒数依 旧没有得到回答消息后,会自己认为主机不可用。对于其他哨兵而言,并不会认为主机不可用。


哨兵会记录这个消息 , 当拥有认为主观下线的哨兵到达 sentinel monitor 所配置的数量的时候 , 就会发起一次新的投票 , 然后切换主机,此时哨兵会重写 Redis 的哨兵配置文件 ,以适应新场景的需要。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
监控 API 开发者
Sentinel之道:流控模式解析与深度探讨
Sentinel之道:流控模式解析与深度探讨
54 0
|
2月前
|
编解码 算法 定位技术
GEE时序——利用sentinel-2(哨兵-2)数据进行地表物候学分析(时间序列平滑法估算和非平滑算法代码)
GEE时序——利用sentinel-2(哨兵-2)数据进行地表物候学分析(时间序列平滑法估算和非平滑算法代码)
78 3
|
2天前
|
监控 NoSQL Redis
Redis的哨兵模式详解
Redis的哨兵模式详解
7 0
|
5天前
|
运维 网络协议 Linux
【运维系列】Centos7安装并配置PXE服务
PXE是Intel开发的预启动执行环境,允许工作站通过网络从远程服务器启动操作系统。它依赖DHCP分配IP,DNS服务分配主机名,TFTP提供引导程序,HTTP/FTP/NFS提供安装源。要部署PXE服务器,需关闭selinux和防火墙,安装dhcpd、httpd、tftp、xinetd及相关服务,配置引导文件和Centos7安装源。最后,通过syslinux安装引导文件,并创建pxelinux.cfg/default配置文件来定义启动参数。
18 0
|
5天前
|
运维 网络协议 Linux
【运维系列】Centos7安装并配置postfix服务
安装CentOS7的Postfix和Dovecot,配置Postfix的`main.cf`文件,包括修改完全域名、允许所有IP、启用邮箱等。然后,配置Dovecot的多个配置文件以启用auth服务和调整相关设置。重启Postfix和Dovecot,设置开机自启,并关闭防火墙进行测试。最后,创建邮箱账户并在Windows邮箱客户端中添加账户设置。
12 0
|
5天前
|
Linux 网络安全
Centos6.5安装并配置NFS服务
该内容描述了在Linux系统中设置NFS服务的步骤。首先挂载yum源,然后安装NFS服务,并编辑配置文件。接着,重启rpcbind和NFS服务,可能需要重复此过程以解决初始可能出现的问题。此外,关闭防火墙策略,并再次重启服务。最终,根目录被共享,特定IP网段被允许访问。
13 0
|
19天前
|
网络协议
centos8 网卡 Nmcli(是network的简写 Nmcli)配置网络
centos8 网卡 Nmcli(是network的简写 Nmcli)配置网络
19 0
|
1月前
|
运维 Linux 应用服务中间件
Centos7如何配置firewalld防火墙规则
Centos7如何配置firewalld防火墙规则
51 0
|
1月前
|
存储 监控 Linux
Flume【部署 02】Flume监控工具Ganglia的安装与配置(CentOS 7.5 在线安装系统监控工具Ganglia + 权限问题处理 + Flume接入监控配置 + 图例说明)
【2月更文挑战第17天】Flume【部署 02】Flume监控工具Ganglia的安装与配置(CentOS 7.5 在线安装系统监控工具Ganglia + 权限问题处理 + Flume接入监控配置 + 图例说明)
29 1
Flume【部署 02】Flume监控工具Ganglia的安装与配置(CentOS 7.5 在线安装系统监控工具Ganglia + 权限问题处理 + Flume接入监控配置 + 图例说明)
|
2月前
|
Ubuntu Linux 网络安全