Redis Sentinel
架构
原理
三个定时任务
- 每十秒每个哨兵节点对所有已知的Redis节点执行
info
操作- 作用:确认当前节点之间的关系,发现新节点,所以配置文件中只需要配置监控主节点,就能监控所有节点
- 每两秒每个哨兵节点通过主节点的
__sentinel__:hello
频道交换信息- 作用:用于不同哨兵之间的通信与感知,所以配置文件中只需要配置监控的主节点,各个哨兵之间就能互相监控
- 每一秒每个哨兵节点对其他哨兵节点和Redis节点执行ping,也就是心跳检测
- 作用:判断是否存活的依据
主观下线与客观下线
- 主观下线:单个哨兵对Redis节点是否在线的看法
- 客观下线:所有哨兵对Redis节点是否在线的看法
- 将自己的认为的主观下线,使用
sentinel is-master-down-by-addr
命令告知其他哨兵自己认为的那个Redis节点主观下线 - 当超过一定票数,则认为该Redis节点离线,所以哨兵个数应该是大于等于3的奇数个,配置的票数一个是一半以上比较好
- 将自己的认为的主观下线,使用
领导者选举
原因:对于故障转移操作,只需要一个哨兵操作即可
选举: sentinel is-master-down-by-addr
命令不仅是告知主观下线,同时也告知其他哨兵希望成为领导者
- 每个做主观下线的哨兵节点向其他哨兵节点发送命令,要求将自己设置为领导者
- 收到命令的哨兵节点如果没有同意其他哨兵节点,那么将同意该请求,否则拒绝
- 如果该哨兵节点发现自己的票数已经超过哨兵集合半数并且超过quorum,那么就会成为领导者
- 如果此过程有多个哨兵节点成为了领导者,则等待一段时间重新进行选举
故障转移具体操作
- 领导者从从节点中选出一个合适的节点作为新的主节点
- 选择优先级最高的从节点,可通过
slave-priority
配置项进行配置,若优先级相同接着向下 - 选择复制偏移量最大的从节点,即复制的最完整的,若偏移量相同接着向下
- 选择runId最小的从节点,即启动最早的节点
- 选择优先级最高的从节点,可通过
- 对选中的节点执行
slave no one
命令让其成为master节点 - 向其余未选中节点发送命令,让他们成为新主节点的从节点,进行同步,复制规则根据具体配置而定
- 更新对原来主节点配置为从节点,并持续进行监控,当其恢复后命令它去同步新的主节点
实现方式
服务端
启动哨兵服务器需要使用redis-sentinel
指定配置文件来启动,由此可见,redis的一下配置项也可以用作redis-sentinel
其中sentinel
前缀的配置项中都需要指定master-name,也就是主从复制架构中的主节点名称,从而达到可监控多套架构的目的,可以自定义取名,默认名称是mymaster
配置项 | 描述 | 默认值 |
---|---|---|
port |
sentinel的端口号 | 26379 |
dir |
sentinel的工作目录 | |
logfile |
sentinel的日志文件 | |
daemonize |
是否以后台守护进程启动 | |
sentinel monitor |
监控的主节点IP和端口,满足客观下线的票数 | 127.0.0.1 6379 2 |
sentinel auth-pass |
监控节点密码 | |
sentinel down-after-milliseconds |
无响应超时时间,超过此时间无响应就会认为该节点主观下线,单位毫秒 | 30000 |
sentinel parallel-syncs mymaster |
在故障转移时的复制规则,即可同时进行复制的节点个数 | 1 |
sentinel failover-timeout |
故障转移的超时时间 | 180000 |
客户端
- 客户端需要知道所有哨兵节点和要访问master-name,因为客户端不知道那个哨兵是活的,所以需要遍历从中选取一个可用的即可,再通过master-name来告知哨兵要访问的是那一套主从复制的架构
- 向哨兵发送
sentinel get-master-addr-by-name masterName
命令, 该哨兵就会返回真正的主节点IP和端口 - 客户端连接该主节点,发送
role
或者role replication
命令,进行确认,确认该节点真的主节点 - 如果主节点发生故障转移,哨兵是能够感知,并通过发布订阅模型将最新的主节点信息告知客户端
Jedis已经封装好了,直接使用即可,仅仅只是连接池变成了哨兵连接池
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); //若不进行配置,则使用的是默认配置
//1. 创建连接池配置对象,进行配置
Set<String> sentinelSet = new HashSet<String>(); //添加多个哨兵的地址
sentinelSet.add("127.0.0.1:26379");
sentinelSet.add("127.0.0.1:26380");
sentinelSet.add("127.0.0.1:26381");
JedisSentinelPool sentinelPool = new JedisSentinelPool("myMaster", sentinelSet, jedisPoolConfig);
//2. 根据配置对象创建哨兵连接池对象
Jedis jedis = null;
try {
jedis = sentinelPool.getResource();
//3. 从连接池中借用Jedis对象
jedis.auth("redis"); //操作数据前设置的密码
String hello = jedis.get("hello");
System.out.println(hello); //world
//4. 通过Jedis执行命令,返回Jedis执行结果
} catch (Exception e) {
System.out.println("发生故障");
} finally {
if (jedis != null) {
jedis.close();
//5. 归还Jedis连接
}
}
节点运维
节点下线
- 哨兵节点:直接关闭即可,其他哨兵节点会自动感知到
- 从节点:直接关闭即可,哨兵节点会自动感知到
- 主节点:选择一个哨兵节点,连接后执行
sentinel failover
命令指定下线的主节点名,该哨兵就会成为领导者进行故障转移操作
节点上线
- 哨兵节点:参考其他哨兵节点启动即可,其他哨兵节点会自动感知到
- 从节点:设置主节点启动即可,哨兵节点会自动感知到
- 主节点:选择一个从节点,连接后执行
config set slave-priority
指定较高的优先级,再选择一个哨兵节点连接执行sentinel failover
命令指定下线的主节点名,该哨兵就会成为领导者进行故障转移操作
Comments NOTHING