redis哨兵高可用

1.redis-sentinel

Redis-Sentinel是redis官方推荐的高可用性解决方案,
当用redis作master-slave的高可用时,如果master本身宕机,redis本身或者客户端都没有实现主从切换的功能。

而redis-sentinel就是一个独立运行的进程,用于监控多个master-slave集群,
自动发现master宕机,进行自动切换slave > master。

2.redis-sentinel功能

1.不时的监控redis是否良好运行,如果节点不可达就会对节点进行下线标识
2.如果被标识的是主节点,sentinel就会和其他的sentinel节点“协商”,如果其他节点也人为主节点不可达,就会选举一个sentinel节点来完成自动故障转义
3.在master-slave进行切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换

3.sentinel的工作方式

每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令


如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。

如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。

当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线

在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令

当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次

若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。

若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。

主观下线和客观下线

主观下线:Subjectively Down,简称 SDOWN,指的是当前 Sentinel 实例对某个redis服务器做出的下线判断。
客观下线:Objectively Down, 简称 ODOWN,指的是多个 Sentinel 实例在对Master Server做出 SDOWN 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,然后开启failover.

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

ODOWN只适用于Master,对于Slave的 Redis 实例,Sentinel 在将它们判断为下线前不需要进行协商, 所以Slave的 Sentinel 永远不会达到ODOWN。

4.redis主从复制背景

Redis主从复制可将主节点数据同步给从节点,从节点此时有两个作用:

1.一旦主节点宕机,从节点作为主节点的备份可以随时顶上来。
2.扩展主节点的读能力,分担主节点读压力。
但是问题是:

    一旦主节点宕机,从节点上位,那么需要人为修改所有应用方的主节点地址(改为新的master地址),还需要命令所有从节点复制新的主节点
那么这个问题,redis-sentinel就可以解决了

5.主从复制架构

6.redis Sentinel架构

7.代码实现

1.环境准备

#三个redis数据实例,配置好 1主2从

#创建文件夹
[root@xujunk data]#mkdir sbredis
[root@xujunk data]#cd sbredis
#创建3个redis配置
[root@xujunk sbredis]#vim 6379.conf
[root@xujunk sbredis]#sed "s/6379/6380/g" 6379.conf > 6380.conf
[root@xujunk sbredis]#sed "s/6379/6381/g" 6379.conf > 6381.conf

"""
    6379.conf
        port 6379
        daemonize yes
        logfile "6379.log"
        dbfilename "dump-6379.rdb"
        dir "/var/redis/data/"

    6380.conf
        port 6380
        daemonize yes
        logfile "6380.log"
        dbfilename "dump-6380.rdb"
        dir "/var/redis/data/"
        slaveof 127.0.0.1 6379

    6381.conf
        port 6381
        daemonize yes
        logfile "6381.log"
        dbfilename "dump-6381.rdb"
        dir "/var/redis/data/"
        slaveof 127.0.0.1 6379
"""
#配置从属关系
[root@xujunk sbredis]#echo "slaveof 127.0.0.1 6379" >> 6380.conf
[root@xujunk sbredis]#echo "slaveof 127.0.0.1 6379" >> 6381.conf

#创建文件用于存储数据和日志
[root@xujunk sbredis]#mkdir -p /var/redis/data/

#启动redis
[root@xujunk sbredis]#redis-server 6379.conf
[root@xujunk sbredis]#redis-server 6380.conf
[root@xujunk sbredis]#redis-server 6381.conf
[root@xujunk sbredis]#!ps
"""
ps -ef |grep redis
root      33158      1  0 21:15 ?        00:00:00 redis-server *:6379
root      33167      1  0 21:15 ?        00:00:00 redis-server *:6380
root      33175      1  1 21:15 ?        00:00:00 redis-server *:6381
root      33186  26372  0 21:15 pts/1    00:00:00 grep --color=auto redis
"""

#三个redis哨兵进程,指定好,检测着谁
#也是准备3个配置文件
sentinel-26379.conf
sentinel-26380.conf
sentinel-26381.conf

[root@xujunk sbredis]#touch sentinel-26379.conf
[root@xujunk sbredis]#vim sentinel-26379.conf
"""
port 26379
dir /var/redis/data/
logfile "26379.log"
sentinel monitor s21ms  127.0.0.1  6379 2
sentinel down-after-milliseconds s21ms  20000
sentinel parallel-syncs s21ms 1
sentinel failover-timeout s21ms 180000
daemonize yes
"""
#分别生成 sentinel-26380.conf        sentinel-26381.conf
[root@xujunk sbredis]#sed "s/26379/26380/g" sentinel-26379.conf > sentinel-26380.conf
[root@xujunk sbredis]#sed "s/26379/26381/g" sentinel-26379.conf > sentinel-26381.conf

2.代码验证

#分别启动 三个redis数据库,  以及三个 哨兵进程 ,注意 ,哨兵第一次启动后,会修改配置文件,如果错了,得删除配置文件,重新写
1.启动哨兵
[root@xujunk sbredis]#redis-sentinel sentinel-26379.conf
[root@xujunk sbredis]#redis-sentinel sentinel-26380.conf
[root@xujunk sbredis]#redis-sentinel sentinel-26381.conf
2.查看后台哨兵,redis运行状态:
[root@xujunk sbredis]#!ps
"""
ps -ef |grep redis
root      33158      1  0 21:15 ?        00:00:00 redis-server *:6379
root      33167      1  0 21:15 ?        00:00:00 redis-server *:6380
root      33175      1  0 21:15 ?        00:00:00 redis-server *:6381
root      33853      1  0 21:24 ?        00:00:00 redis-sentinel *:26379 [sentinel]
root      33870      1  0 21:24 ?        00:00:00 redis-sentinel *:26380 [sentinel]
root      33877      1  1 21:24 ?        00:00:00 redis-sentinel *:26381 [sentinel]
"""
#运行状态正常
3.验证哨兵是否正常:
[root@xujunk sbredis]#redis-cli -p 26379 info sentinel
"""
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=s21ms,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3

"""
#name=s21ms,主节点address=127.0.0.1:6379  从节点2个 哨兵3个

3.干掉主库(主节点) ,检查主从切换状态
[root@xujunk sbredis]#kill -9 33158
4.查看从库(从节点)6380,6381  :
[root@xujunk sbredis]#redis-cli -p 6380 info replication
"""
# Replication
role:master         #主节点
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=85816,lag=0
master_replid:9450087193f724b8538d25eef9336803ce96e71b
master_replid2:d43267907dd90579d5c9ef10af38464e49f23ba2
master_repl_offset:85816
second_repl_offset:84624
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:85816
"""
[root@xujunk sbredis]#redis-cli -p 6381 info replication
"""
# Replication
role:slave          #从节点
master_host:127.0.0.1
master_port:6380    #归属6380端口
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:87130
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:9450087193f724b8538d25eef9336803ce96e71b
master_replid2:d43267907dd90579d5c9ef10af38464e49f23ba2
master_repl_offset:87130
second_repl_offset:84624
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:87130
"""
#可以看出6380端口切换成主库(主节点),6381端口切换成6380端口的从节点

3.哨兵配置内容介绍:

    port 26379
    dir /var/redis/data/
    logfile "26379.log"

    // 当前Sentinel节点监控 192.168.182.130:6379 这个主节点
    // 2代表判断主节点失败至少需要2个Sentinel节点节点同意
    // mymaster是主节点的别名
    sentinel monitor s21ms  0.0.0.0 6379 2

    //每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过30000毫秒30s且没有回复,则判定不可达
    sentinel down-after-milliseconds s21ms  20000

    //当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,
    原来的从节点会向新的主节点发起复制操作,限制每次向新的主节点发起复制操作的从节点个数为1
    sentinel parallel-syncs mymaster 1

    //故障转移超时时间为180000毫秒
    sentinel failover-timeout mymaster 180000
01-22 07:03