- 1 介绍
- 2 配置文件
- 1 复制一份sentinel.conf文件
- 2 将相关配置修改为如下值:
- 3 哨兵配置
- sentinel monitor是哨兵最核心的配置
- masterName指定了主节点名称,masterIp和masterPort指定了主节点地址
- quorum是判断主节点客观下线的哨兵数量阈值:
- 当判定主节点下线的哨兵数量达到quorum时,对主节点进行客观下线
- 建议取值为哨兵数量的一半加1
- 哨兵使用ping命令对其他节点进行心跳检测
- 如果其他节点超过down-after-milliseconds配置的时间没有回复
- 哨兵就会将其进行主观下线
- 该配置对主节点、从节点和哨兵节点的主观下线判定都有效
- 与故障转移之后从节点的复制有关
- 它规定了每次向新的主节点发起复制操作的从节点个数
- 如果parallel-syncs=1,则从节点会一个一个开始复制
- 与故障转移超时的判断有关
- 该参数不是用来判断整个故障转移阶段的超时,而是其几个子阶段的超时
- 例如如果主节点晋升从节点时间超过timeout
- 或从节点向新的主节点发起复制操作的时间(不包括复制数据的时间)超过timeout
- 4 基本原理
1 介绍
在 主从复制 中曾提到,Redis主从复制的作用有数据热备、负载均衡、故障恢复等;但主从复制存在的一个问题是故障恢复无法自动化。本文将要介绍的哨兵,它基于Redis主从复制,主要作用便是解决主节点故障恢复的自动化问题,进一步提高系统的高可用性。
Redis Sentinel,即Redis哨兵,是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点。哨兵架构下,client 端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel代理访问 redis 的主节点,当redis的主节点发生变化,哨兵会第一时间感知到,并且将新的 redis 主节点通知给 client 端(这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息)。哨兵的核心功能是主节点的自动故障转移,下面是Redis官方文档对于哨兵功能的描述:
- 监控(Monitoring):哨兵会不断地检查主节点和从节点是否运作正常。
- 自动故障转移(Automatic failover):当主节点不能正常工作时,哨兵会开始自动故障转移操作,它会将失效主节点的其中一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点。
- 配置提供者(Configuration provider):客户端在初始化时,通过连接哨兵来获得当前Redis服务的主节点地址。
- 通知(Notification):哨兵可以将故障转移的结果发送给客户端。
其中,监控和自动故障转移功能,使得哨兵可以及时发现主节点故障并完成转移;而配置提供者和通知功能,则需要在与客户端的交互中才能体现。
2 配置文件
- 复制多分哨兵的配置文件,文件内容如下
- 启动Redis主从实例
- 启动哨兵集群,
redis-sentinel sentinel_26379.conf
。 ```scala1 复制一份sentinel.conf文件
cp sentinel.conf sentinel_26379.conf
2 将相关配置修改为如下值:
port 26379 daemonize yes protected-mode no pidfile “/var/run/redis-sentinel-26379.pid” logfile “26379.log” dir “/usr/local/redis-5.0.3/data”
3 哨兵配置
sentinel monitor是哨兵最核心的配置
masterName指定了主节点名称,masterIp和masterPort指定了主节点地址
quorum是判断主节点客观下线的哨兵数量阈值:
当判定主节点下线的哨兵数量达到quorum时,对主节点进行客观下线
建议取值为哨兵数量的一半加1
sentinel monitor {masterName} {masterIp} {masterPort} {quorum}
哨兵使用ping命令对其他节点进行心跳检测
如果其他节点超过down-after-milliseconds配置的时间没有回复
哨兵就会将其进行主观下线
该配置对主节点、从节点和哨兵节点的主观下线判定都有效
sentinel down-after-milliseconds {masterName} {time}
与故障转移之后从节点的复制有关
它规定了每次向新的主节点发起复制操作的从节点个数
如果parallel-syncs=1,则从节点会一个一个开始复制
sentinel parallel-syncs {masterName} {number}
与故障转移超时的判断有关
该参数不是用来判断整个故障转移阶段的超时,而是其几个子阶段的超时
例如如果主节点晋升从节点时间超过timeout
或从节点向新的主节点发起复制操作的时间(不包括复制数据的时间)超过timeout
sentinel failover-timeout {masterName} {time}
<a name="IXlKo"></a>
### 3 Java客户端
<a name="SeE1M"></a>
#### 3.1 Jedis
```java
public class JedisSentinelTest {
public static void main(String[] args) throws IOException {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(20);
config.setMaxIdle(10);
config.setMinIdle(5);
String masterName = "mymaster";
Set<String> sentinels = new HashSet<String>();
sentinels.add(new HostAndPort("192.168.0.60",26379).toString());
sentinels.add(new HostAndPort("192.168.0.60",26380).toString());
sentinels.add(new HostAndPort("192.168.0.60",26381).toString());
// JedisSentinelPool其实本质跟JedisPool类似,都是与redis主节点建立的连接池
// JedisSentinelPool并不是说与sentinel建立的连接池,而是通过sentinel发现redis主节点并与其建立连接
JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName, sentinels, config, 3000, null);
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
System.out.println(jedis.set("sentinel", "123"));
} catch (Exception e) {
e.printStackTrace();
} finally {
// 注意这里不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池。
if (jedis != null)
jedis.close();
}
}
}
3.2 Spring Boot
spring:
redis:
database: 0
timeout: 3000
sentinel: # 哨兵模式
master: mymaster # 主服务器所在集群名称
nodes: 192.168.0.60:26379,192.168.0.60:26380,192.168.0.60:26381
lettuce:
pool:
max-idle: 50
min-idle: 10
max-active: 100
max-wait: 1000
3.3 客户端原理
在整个过程中,我们的代码不需要显式的指定主节点的地址,就可以连接到主节点;代码中对故障转移没有任何体现,就可以在哨兵完成故障转移后自动的切换主节点。之所以可以做到这一点,是因为在JedisSentinelPool的构造器中,进行了相关的工作;主要包括以下两点:
- 遍历哨兵节点,获取主节点信息:遍历哨兵节点,通过其中一个哨兵节点+masterName获得主节点的信息;该功能是通过调用哨兵节点的
sentinel get-master-addr-by-name
命令实现,一旦获得主节点信息,停止遍历(因此一般来说遍历到第一个哨兵节点,循环就停止了)。 - 增加对哨兵的监听:这样当发生故障转移时,客户端便可以收到哨兵的通知,从而完成主节点的切换。具体做法是:利用redis提供的发布订阅功能,为每一个哨兵节点开启一个单独的线程,订阅哨兵节点的+switch-master频道,当收到消息时,重新初始化连接池。
4 基本原理
关于哨兵的原理,关键是了解以下几个概念。
- 定时任务:每个哨兵节点维护了3个定时任务。定时任务的功能分别如下:
- 通过向主从节点发送info命令获取最新的主从结构;
- 通过发布订阅功能获取其他哨兵节点的信息;
- 通过向其他节点发送ping命令进行心跳检测,判断是否下线。
- 主观下线:在心跳检测的定时任务中,如果其他节点超过一定时间没有回复,哨兵节点就会将其进行主观下线。顾名思义,主观下线的意思是一个哨兵节点“主观地”判断下线;与主观下线相对应的是客观下线。
- 客观下线:哨兵节点在对主节点进行主观下线后,会通过
sentinel is-master-down-by-addr
命令询问其他哨兵节点该主节点的状态;如果判断主节点下线的哨兵数量达到一定数值,则对该主节点进行客观下线。需要特别注意的是,客观下线是主节点才有的概念;如果从节点和哨兵节点发生故障,被哨兵主观下线后,不会再有后续的客观下线和故障转移操作。 - 选举领导者哨兵节点:当主节点被判断客观下线以后,各个哨兵节点会进行协商,选举出一个领导者哨兵节点,并由该领导者节点对其进行故障转移操作。监视该主节点的所有哨兵都有可能被选为领导者,选举使用的算法是Raft算法;Raft算法的基本思路是先到先得:即在一轮选举中,哨兵A向B发送成为领导者的申请,如果B没有同意过其他哨兵,则会同意A成为领导者。选举的具体过程这里不做详细描述,一般来说,哨兵选择的过程很快,谁先完成客观下线,一般就能成为领导者。
- 故障转移:选举出的领导者哨兵,开始进行故障转移操作,该操作大体可以分为3个步骤:
- 在从节点中选择新的主节点:选择的原则是,首先过滤掉不健康的从节点;然后选择优先级最高的从节点(由
slave-priority
指定);如果优先级无法区分,则选择复制偏移量最大的从节点;如果仍无法区分,则选择runid最小的从节点。 - 更新主从状态:通过
replicaof no one
命令,让选出来的从节点成为主节点;并通过replicaof命令让其他节点成为其从节点。 - 将已经下线的主节点(假设是6379)设置为新的主节点的从节点,当6379重新上线后,它会成为新的主节点的从节点。
- 在从节点中选择新的主节点:选择的原则是,首先过滤掉不健康的从节点;然后选择优先级最高的从节点(由