Redis Sentinel 哨兵模式

https://blog.csdn.net/panchang199266/article/details/81463026

  下文参见Sentinel
(一)Redis Sentinel 模式简介
  Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:

  • 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
  • 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
  • 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作,它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器;当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。

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

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

(二)启动 Sentinel
  对于 redis-sentinel 程序, 你可以用以下命令来启动 Sentinel 系统:

./redis-sentinel /path/to/sentinel.conf
   
   
  • 1

  对于 redis-server 程序, 你可以用以下命令来启动一个运行在 Sentinel 模式下的 Redis 服务器:

./redis-server /path/to/sentinel.conf --sentinel
   
   
  • 1

  两种方法都可以启动一个 Sentinel 实例。

  启动 Sentinel 实例必须指定相应的配置文件, 系统会使用配置文件来保存 Sentinel 的当前状态, 并在 Sentinel 重启时通过载入配置文件来进行状态还原。

  如果启动 Sentinel 时没有指定相应的配置文件, 或者指定的配置文件不可写(not writable), 那么 Sentinel 会拒绝启动。

(三)故障排除的流程
这里写图片描述

(四)环境准备
  1、配置1主2从redis-server
这里写图片描述
这里写图片描述
  备注:
  (1)由于当主节点发生故障时,原本的从节点会提升为主节点,所以从节点也必须能写能读,所以slave-read-only yes这个选项必须注释掉。否则当从节点提升为主节点时,只能读不能写!
  (2)在配置从节点时,记得将slave 127.0.0.1 7000改为slave 服务器ip 7000。必须改为真实的服务器ip,否则当客户端远程连接节点时,会将其识别为本机。

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

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

//守护进程,后台启动
daemonize yes
sentinel monitor mymaster 192.168.10.130 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
sentinel monitor resque 192.168.1.1 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5
   
   

  第一行配置指示 Sentinel 去监视一个名为 mymaster 的主服务器, 这个主服务器的 IP 地址为 192.168.10.130 , 端口号为 6379 , 而将这个主服务器判断为失效至少需要 2 个 Sentinel 同意 (只要同意 Sentinel 的数量不达标,自动故障迁移就不会执行)。

  不过要注意, 无论你设置要多少个 Sentinel 同意才能判断一个服务器失效, 一个 Sentinel 都需要获得系统中多数(majority) Sentinel 的支持, 才能发起一次自动故障迁移, 并预留一个给定的配置纪元 (configuration Epoch ,一个配置纪元就是一个新主服务器配置的版本号)。

  换句话说, 在只有少数(minority) Sentinel 进程正常运作的情况下, Sentinel 是不能执行自动故障迁移的。

  其他选项的基本格式如下:

sentinel <选项的名字> <主服务器的名字> <选项的值>
   
   
  • 1

各个选项的功能如下:

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

    如果服务器在给定的毫秒数之内, 没有返回 Sentinel 发送的 PING 命令的回复, 或者返回一个错误, 那么 Sentinel
    将这个服务器标记为主观下线(subjectively down,简称 SDOWN )。

    不过只有一个 Sentinel 将服务器标记为主观下线并不一定会引起服务器的自动故障迁移: 只有在足够数量的 Sentinel
    都将一个服务器标记为主观下线之后, 服务器才会被标记为客观下线(objectively down, 简称 ODOWN ),
    这时自动故障迁移才会执行。

    将服务器标记为客观下线所需的 Sentinel 数量由对主服务器的配置决定。

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

    如果从服务器被设置为允许使用过期数据集(参见对 redis.conf 文件中对 slave-serve-stale-data
    选项的说明), 那么你可能不希望所有从服务器都在同一时间向新的主服务器发送同步请求, 因为尽管复制过程的绝大部分步骤都不会阻塞从服务器,
    但从服务器在载入主服务器发来的 RDB 文件时, 仍然会造成从服务器在一段时间内不能处理命令请求:
    如果全部从服务器一起对新的主服务器进行同步, 那么就可能会造成所有从服务器在短时间内全部不可用的情况出现。

    你可以通过将这个值设为 1 来保证每次只有一个从服务器处于不能处理命令请求的状态。

  3、开启redis-server和redis-sentinel

//开启redis-server
./redis-server server配置文件

//开启redis-sentinel
./redis-sentinel sentinel配置文件

  备注:注意开启redis-server和redis-sentinel的命令不一样

(五)客户端访问

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
 * @author 咸鱼
 * @date 2018/7/1 22:04
 */
public class RedisTest {
   
   
    private static final Logger LOGGER = LoggerFactory.getLogger(RedisTest.class);
    @Test
    public void testRedisSentinel(){
        String masterName = "mymaster";
        //这里主要是向set集合中增加数据,所有底层用链表效率最高
        Set<String> sentinels = new HashSet<>();
        //为了redis客户端可以远程连接这些端口,需要在linux服务器上开启这些端口
        sentinels.add("192.168.10.130:26379");
        sentinels.add("192.168.10.130:26380");
        sentinels.add("192.168.10.130:26381");
        //创建JedisSentinel线程池
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxIdle(8);
        poolConfig.setMinIdle(0);
        poolConfig.setMaxTotal(8);
//        JedisSentinelPool pool = new JedisSentinelPool(masterName, sentinels, poolConfig);
        //超时时间:毫秒
        JedisSentinelPool pool = new JedisSentinelPool(masterName, sentinels, poolConfig, 10000);
        int counter = 0;
        while (true){
            //获取redis客户端
            Jedis jedis = null;
            try {
                jedis = pool.getResource();
                int index = new Random().nextInt(10000);
                String key = "k-" + index;
                String value = "v-" + index;
                jedis.set(key, value);
                counter++;
                if (counter % 100 == 0){
                    LOGGER.info("{} value is {}", key, jedis.get(key));
                }
                //休息10秒
                TimeUnit.MILLISECONDS.sleep(10);
            } catch (Exception e){
                LOGGER.error(e.getMessage(), e);
            } finally {
                if (jedis != null){
                    jedis.close();
                }
            }
        }
    }
}
 
 

(六)主观下线和客观下线
  前面说过, Redis 的 Sentinel 中关于下线(down)有两个不同的概念:

  • 主观下线(Subjectively Down, 简称 SDOWN)指的是单个 Sentinel 实例对服务器做出的下线判断。
  • 客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断。 (一个Sentinel 可以通过向另一个 Sentinel 发送 SENTINEL is-master-down-by-addr命令来询问对方是否认为给定的服务器已下线。)

  如果一个服务器没有在 master-down-after-milliseconds 选项所指定的时间内, 对向它发送 PING 命令的 Sentinel 返回一个有效回复(valid reply), 那么 Sentinel 就会将这个服务器标记为主观下线。

  服务器对 PING 命令的有效回复可以是以下三种回复的其中一种:

  • 返回 +PONG 。
  • 返回 -LOADING 错误。
  • 返回 -MASTERDOWN 错误。

  如果服务器返回除以上三种回复之外的其他回复, 又或者在指定时间内没有回复 PING 命令, 那么 Sentinel 认为服务器返回的回复无效(non-valid)。

  注意, 一个服务器必须在 master-down-after-milliseconds 毫秒内, 一直返回无效回复才会被 Sentinel 标记为主观下线。

  举个例子, 如果 master-down-after-milliseconds 选项的值为 30000 毫秒(30 秒), 那么只要服务器能在每 29 秒之内返回至少一次有效回复, 这个服务器就仍然会被认为是处于正常状态的。

  从主观下线状态切换到客观下线状态并没有使用严格的法定人数算法(strong quorum algorithm), 而是使用了流言协议: 如果 Sentinel 在给定的时间范围内, 从其他 Sentinel 那里接收到了足够数量的主服务器下线报告, 那么 Sentinel 就会将主服务器的状态从主观下线改变为客观下线。 如果之后其他 Sentinel 不再报告主服务器已下线, 那么客观下线状态就会被移除。

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

  只要一个 Sentinel 发现某个主服务器进入了客观下线状态, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对失效的主服务器执行自动故障迁移操作。

(七)每个 Sentinel 都需要定期执行的任务

  • 每个 Sentinel 以每秒钟一次的频率向它所知的主服务器、从服务器以及其他 Sentinel 实例发送一个 PING 命令。
  • 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds选项所指定的值, 那么这个实例会被 Sentinel 标记为主观下线。 一个有效回复可以是: +PONG 、 -LOADING 或者 -MASTERDOWN。
  • 如果一个主服务器被标记为主观下线, 那么正在监视这个主服务器的所有 Sentinel
    要以每秒一次的频率确认主服务器的确进入了主观下线状态。
  • 如果一个主服务器被标记为主观下线, 并且有足够数量的 Sentinel (至少要达到配置文件指定的数量)在指定的时间范围内同意这一判断,那么这个主服务器被标记为客观下线。
  • 在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有主服务器和从服务器发送 INFO 命令。 当一个主服务器被 Sentinel 标记为客观下线时, Sentinel 向下线主服务器的所有从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
  • 当没有足够数量的 Sentinel 同意主服务器已经下线, 主服务器的客观下线状态就会被移除。 当主服务器重新向 Sentinel 的PING 命令返回有效回复时, 主服务器的主管下线状态就会被移除。

(八)自动发现 Sentinel 和从服务器

  一个 Sentinel 可以与其他多个 Sentinel 进行连接, 各个 Sentinel 之间可以互相检查对方的可用性, 并进行信息交换。

  你无须为运行的每个 Sentinel 分别设置其他 Sentinel 的地址, 因为 Sentinel 可以通过发布与订阅功能来自动发现正在监视相同主服务器的其他 Sentinel , 这一功能是通过向频道 sentinel:hello 发送信息来实现的。

  与此类似, 你也不必手动列出主服务器属下的所有从服务器, 因为 Sentinel 可以通过询问主服务器来获得所有从服务器的信息。

  • 每个 Sentinel 会以每两秒一次的频率, 通过发布与订阅功能, 向被它监视的所有主服务器和从服务器的sentinel:hello 频道发送一条信息, 信息中包含了 Sentinel 的 IP 地址、端口号和运行 ID (runid)。
  • 每个 Sentinel 都订阅了被它监视的所有主服务器和从服务器的 sentinel:hello 频道, 查找之前未出现过的sentinel (looking for unknown sentinels)。 当一个 Sentinel 发现一个新的Sentinel 时, 它会将新的 Sentinel 添加到一个列表中, 这个列表保存了 Sentinel 已知的,监视同一个主服务器的所有其他 Sentinel 。
  • Sentinel 发送的信息中还包括完整的主服务器当前配置(configuration)。 如果一个 Sentinel包含的主服务器配置比另一个 Sentinel 发送的配置要旧, 那么这个 Sentinel 会立即升级到新配置上。
  • 在将一个新 Sentinel 添加到监视主服务器的列表上面之前, Sentinel 会先检查列表中是否已经包含了和要添加的Sentinel 拥有相同运行 ID 或者相同地址(包括 IP 地址和端口号)的 Sentinel , 如果是的话, Sentinel会先移除列表中已有的那些拥有相同运行 ID 或者相同地址的 Sentinel , 然后再添加新 Sentinel 。

(九)领导者选举原理抽象
这里写图片描述

(十)故障转移原理
这里写图片描述

  关于“从slave节点中选出一个“合适的”节点作为新的master节点”中的合适的条件如下:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值