Redis哨兵(Sentinel)模式
主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。
一、哨兵模式概述
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
哨兵节点由两部分组成,哨兵节点和数据节点(如图):
哨兵节点
:哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的redis节点,不存储数据。
数据节点
:主节点和从节点都是数据节点。
访问redis集群的数据都是通过哨兵集群的,哨兵监控整个redis集群。
一旦发现redis集群出现了问题,比如刚刚说的主节点挂了,从节点会顶上来。但是主节点地址变了,这时候应用服务无感知,也不用更改访问地址,因为哨兵才是和应用服务做交互的。
Sentinel 很好的解决了故障转移,在高可用方面又上升了一个台阶,当然Sentinel还有其他功能。
比如 主节点存活检测、主从运行情况检测、主从切换。
Redis的Sentinel最小配置是 一主一从。
二、哨兵模式监控的原理
每个Sentinel以 每秒钟 一次的频率,向它所有的 主服务器、从服务器 以及其他Sentinel实例 发送一个PING 命令。
如果一个 实例(instance)距离最后一次有效回复 PING命令的时间超过 down-after-milliseconds 所指定的值,那么这个实例会被 Sentinel标记为 主观下线。
如果一个 主服务器 被标记为 主观下线,那么正在 监视 这个 主服务器 的所有 Sentinel 节点,要以 每秒一次 的频率确认 该主服务器是否的确进入了 主观下线 状态。
如果一个 主服务器 被标记为 主观下线,并且有 足够数量 的 Sentinel(至少要达到配置文件指定的数量)在指定的 时间范围 内同意这一判断,那么这个该主服务器被标记为 客观下线。
在一般情况下, 每个 Sentinel 会以每 10秒一次的频率,向它已知的所有 主服务器 和 从服务器 发送 INFO 命令。
当一个 主服务器 被 Sentinel标记为 客观下线 时,Sentinel 向 下线主服务器 的所有 从服务器 发送 INFO 命令的频率,会从10秒一次改为 每秒一次。
Sentinel和其他 Sentinel 协商 主节点 的状态,如果 主节点处于 SDOWN`状态,则投票自动选出新的主节点。将剩余的 从节点 指向 新的主节点 进行 数据复制。
当没有足够数量的 Sentinel 同意 主服务器 下线时, 主服务器 的 客观下线状态 就会被移除。当 主服务器 重新向 Sentinel的PING命令返回 有效回复 时,主服务器 的 主观下线状态 就会被移除。
哨兵模式的优缺点
优点
哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都具有。主从可以自动切换,系统更健壮,可用性更高。Sentinel 会不断的检查 主服务器 和 从服务器 是否正常运行。当被监控的某个 Redis 服务器出现问题,Sentinel 通过API脚本向管理员或者其他的应用程序发送通知。
缺点
Redis较难支持在线扩容,对于集群,容量达到上限时在线扩容会变得很复杂。
附:配置3个哨兵和1主2从的Redis服务器来演示这个过程
服务类型 | 是否是主服务器 | IP地址 | 端口 |
---|---|---|---|
Redis | 是 | 192.168.10.8 | 6379 |
Redis | 否 | 192.168.10.9 | 6379 |
Redis | 否 | 192.168.10.10 | 6379 |
Sentinel | - | 192.168.10.8 | 26379 |
Sentinel | - | 192.168.10.9 | 26379 |
Sentinel | - | 192.168.10.10 | 26379 |
master节点配置
# 使得Redis服务器可以跨网络访问
bind 0.0.0.0
# 设置密码
requirepass "123456"
slave节点配置
# 使得Redis服务器可以跨网络访问
bind 0.0.0.0
# 设置密码
requirepass "123456"
# 指定主服务器
slaveof 192.168.10.8 6379
# 主服务器密码
masterauth 123456
daemonize yes
logfile /var/log/redis/sentinel.log
dir /var/lib/redis-sentinel # 修改 dir /tmp
# 配置监听的主服务器,这里sentinel monitor代表监控,mymaster代表服务器的名称,可以自定义,192.168.10.8代表监控的主服务器,6379代表端口,2代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。
# 全文查找替换配置文件中的mymaster替换为redis-master (sed 's/mymaster/redis-master/g' sentinel.conf > sentinel-new.conf)
sentinel monitor redis-master 192.168.10.8 6379 2 # 这里的IP地址不能写成127.1.0.1
sentinel down-after-milliseconds redis-master 30000
# sentinel author-pass 定义服务的密码,mymaster是服务名称,123456是Redis服务器密码
sentinel auth-pass redis-master 123456
sentinel parallel-syncs redis-master 1
sentinel failover-timeout redis-master 180000
启动redis和sentinel,注意首先是主机(192.168.11.128)的Redis服务进程,然后启动从机的服务进程,最后启动3个哨兵的服务进程
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
/usr/local/redis/bin/redis-sentinel /usr/local/redis/etc/sentinel.conf
Java代码示例
JedisPoolConfig config = new JedisPoolConfig();
// jedis最大空闲数
config.setMaxIdle(50);
// 设置最小空闲数
config.setMinIdle(10);
// jedis池没有对象返回时,最大等待时间
config.setMaxWaitMillis(3000L);
// 设置最大连接
config.setMaxTotal(500);
// jedis调用borrowObject方法时,是否进行有效检查
config.setTestOnBorrow(false);
// jedis调用returnObject方法时,是否进行有效检查
config.setTestOnReturn(false);
// Idle时进行连接扫描
config.setTestWhileIdle(false);
// 表示idle object evitor两次扫描之间要sleep的毫秒数
config.setTimeBetweenEvictionRunsMillis(30000);
// 表示idle object evitor每次扫描的最多的对象数
config.setNumTestsPerEvictionRun(10);
// 表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
config.setMinEvictableIdleTimeMillis(60000);
// 哨兵信息
Set sentinels = new HashSet();
sentinels.add("192.168.10.8:26379");
sentinels.add("192.168.10.9:26379");
sentinels.add("192.168.10.10:26379");
// 创建连接池
JedisSentinelPool pool = new JedisSentinelPool("redis-master", sentinels, config, null);