redis主从切换---Sentinel(哨兵模式)

Sentinel
Redis Sentinel 是一个分布式系统,用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:

1、监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。

2、提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。

3、自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时,Redis Sentinel 可以将一个从服务器升级为主服务器, 并对其他从服务器进行配置,让它们使用新的主服务器。当应用程序连接Redis 服务器时, Redis Sentinel会告之新的主服务器地址和端口。

注意:在使用sentinel监控主从节点的时候,从节点需要是使用动态方式配置的,如果直接修改配置文件,后期sentinel实现故障转移的时候会出问题。

你可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。

主观下线和客观下线:

1、主观下线(Subjectively Down, 简称 SDOWN)指的是单个 Sentinel 实例对服务器做出的下线判断。当一个sentinel认为一个redis服务连接不上的时候,会给这个服务打个标记为下线状态。

2、客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断。 (一个 Sentinel 可以通过向另一个 Sentinel 发送 SENTINEL is-master-down-by-addr 命令来询问对方是否认为给定的服务器已下线。) 当多个sentinel认为一个redids连接不上的时候,则认为这个redis服务确实下线了。这里的多个sentinel的个数可以在配置文件中设置。

注意: 一个服务器必须在 master-down-after-milliseconds 毫秒内, 一直返回无效回复才会被 Sentinel 标记为主观下线。
举个栗子, 如果 master-down-after-milliseconds 选项的值为 30000 毫秒(30 秒), 那么只要服务器能在每 29 秒之内返回至少一次有效回复,
这个服务器就仍然会被认为是处于正常状态的。

SDOWN:适用于Master和Slave,只要一个 Sentinel 发现Master进入了ODOWN, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对下线的主服务器执行自动故障迁移操作。

ODOWN:只适用于Master,对于任何其他类型的 Redis 实例,Sentinel 在将它们判断为下线前不需要进行协商, 所以从服务器或者其他 Sentinel永远不会达到客观下线条件。

注意:主观下线条件适用于主服务器和从服务器,客观下线条件只适用于主服务器。

sentinel配置

Redis 源码中包含了一个名为 sentinel.conf 的文件, 这个文件是一个带有详细注释的 Sentinel 配置文件示例。

运行一个 Sentinel 所需的最少配置如下所示:

port 26379
    #sentinel端口

sentinel monitor mymaster 192.168.1.93 6379 1
    #哨兵监控的master,主从配置一样。
    #这个主服务器的 IP 地址为 192.168.1.93,端口号为 6379。
    #而将这个主服务器判断为失效至少需要 2 个 Sentinel 同意。
    #只要同意 Sentinel 的数量不达标,自动故障迁移就不会执行。
    #不过要注意,无论你设置要多少个Sentinel同意才能判断一个服务器失效。
    #一个 Sentinel 都需要获得系统中多数(majority)Sentinel 的支持, 才能发起一次自动故障迁移。
    #换句话说, 在只有少数(minority) Sentinel 进程正常运作的情况下, Sentinel 是不能执行自动故障迁移的。

sentinel down-after-milliseconds mymaster 30000
    #down-after-milliseconds 选项指定了 Sentinel 认为服务器已经断线所需的毫秒数。

sentinel parallel-syncs mymaster 1
    #parallel-syncs 选项指定了在执行故障转移时,最多可以有多少个从服务器同时对新的主服务器进行同步。
    #这个数字越小,完成故障转移所需的时间就越长。

sentinel failover-timeout resque 180000
    #如果在该时间(ms)内未能完成failover操作,则认为该failover失败。

sentinel auth-pass mymaster 123456
    #设置连接master和slave时的密码,注意的是sentinel不能分别为master和slave设置不同的密码,因此master和slave的密码应该设置相同。

启动Sentinel

虽然 Redis Sentinel 释出为一个单独的可执行文件 redis-sentinel , 但实际上它只是一个运行在特殊模式下的 Redis 服务器, 你可以在启动一个普通 Redis 服务器时通过给定 –sentinel 选项来启动 Redis Sentinel 。

启动redis,主从都要启动。

[root@localhost src]# ./redis-server ../redis.conf 

启动群集监控,主从都要启动。注意:首次启动时,必须先启动Master。

[root@localhost src]# ./redis-sentinel ../sentinel.conf 

redis主从切换---Sentinel(哨兵模式)_第1张图片

redis主从切换---Sentinel(哨兵模式)_第2张图片

启动状态:

redis主从切换---Sentinel(哨兵模式)_第3张图片

redis主从切换---Sentinel(哨兵模式)_第4张图片

启动报错处理:

这里写图片描述

如果想要永久解决,打开/etc/sysctl.conf,在这里面添net.core.somaxconn= 1024 然后执行sysctl -p 就可以永久消除这个warning。

kernel.shmall = 4294967296
net.core.somaxconn= 1024
[root@localhost ~]# vim /etc/sysctl.conf 
[root@localhost ~]# sysctl -p
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
error: "net.bridge.bridge-nf-call-ip6tables" is an unknown key
error: "net.bridge.bridge-nf-call-iptables" is an unknown key
error: "net.bridge.bridge-nf-call-arptables" is an unknown key
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.core.somaxconn = 1024
[root@localhost ~]# 

java连接Sentinel

import java.util.HashSet;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;

public class SentinelTest {

    public static void main(String[] args) {
        //使用HashSet添加多个sentinel
        HashSet sentinels = new HashSet();
        //添加sentinel主机和端口
        sentinels.add("192.168.1.93:26379");

        //创建config
        JedisPoolConfig config = new JedisPoolConfig();
        //最大空闲连接数, 默认8个
        config.setMaxIdle(8);
        //最大连接数, 默认8个
        config.setMaxTotal(8);
        //获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,  默认-1
        config.setMaxWaitMillis(-1);
        //在获取连接的时候检查有效性, 默认false
        config.setTestOnBorrow(false);

        // 通过Jedis连接池创建一个Sentinel连接池  
        JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels, config);
        // 获取master的主机和端口
        HostAndPort hostAndPort = pool.getCurrentHostMaster();
        System.out.println(hostAndPort.getHost() + " :" + hostAndPort.getPort());
        // 从Sentinel池中获取资源
        Jedis resource = pool.getResource();
        resource.auth("123456");
        // 打印资源中key为name的值
        System.out.println("name:" + resource.get("name"));

        // 关闭资源
        resource.close();
    }

}

报异常啦

九月 20, 2017 5:29:19 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Trying to find master from available Sentinels...
九月 20, 2017 5:29:19 下午 redis.clients.jedis.JedisSentinelPool initSentinels
警告: Cannot get master address from sentinel running @ 192.168.1.93:26379. Reason: redis.clients.jedis.exceptions.JedisDataException: DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted from the loopback interface. If you want to connect from external computers to Redis you may adopt one of the following solutions: 1) Just disable protected mode sending the command 'CONFIG SET protected-mode no' from the loopback interface by connecting to Redis from the same host the server is running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use CONFIG REWRITE to make this change permanent. 2) Alternatively you can just disable the protected mode by editing the Redis configuration file, and setting the protected mode option to 'no', and then restarting the server. 3) If you started the server manually just for testing, restart it with the '--protected-mode no' option. 4) Setup a bind address or an authentication password. NOTE: You only need to do one of the above things in order for the server to start accepting connections from the outside.. Trying next one.
Exception in thread "main" redis.clients.jedis.exceptions.JedisConnectionException: All sentinels down, cannot determine where is mymaster master is running...
    at redis.clients.jedis.JedisSentinelPool.initSentinels(JedisSentinelPool.java:180)
    at redis.clients.jedis.JedisSentinelPool.(JedisSentinelPool.java:95)
    at redis.clients.jedis.JedisSentinelPool.(JedisSentinelPool.java:82)
    at redis.clients.jedis.JedisSentinelPool.(JedisSentinelPool.java:70)
    at redis.clients.jedis.JedisSentinelPool.(JedisSentinelPool.java:39)
    at com.redis.SentinelTest.main(SentinelTest.java:31)

解决方法:
编辑sentinel.conf文件,去掉protected-mode no的注释,主从同步。

protected-mode no

redis主从切换---Sentinel(哨兵模式)_第5张图片

你可能感兴趣的:(redis)