华子目录
redis_1">为什么会出现redis的哨兵?
redis_4">redis哨兵
Sentinel进程
是用于监控redis集群
中Master主服务器
工作的状态
,在Master主服务器
发生故障的时候
,可以实现Master和Slave服务器
的切换
,保证系统
的高可用
每个哨兵(Sentinel)进程
会向其它哨兵(Sentinel)
:Master、Slave
定时发送消息
,以确认
对方是否存活
,如果发现对方
在指定配置时间内
未得到回应
,则暂时认为
对方已离线
,也就是所谓的主观认为宕机
(主观
:是每个成员
都具有的
,是独自的
,而且可能相同
也可能不同
的意识
)。英文名称
:Subjective Down
,简称SDOWN
- 有
主观宕机
,对应
的有客观宕机
。当哨兵群
中的多数Sentinel进程
在对Master主服务器
做出SDOWN
的判断
,并且通过Sentinel is-master-down-by-addr命令
互相交流之后
,得出的Master Server下线判断
,这种方式就是客观宕机
(客观
:是不依赖于某种意识,而是已经实际存在的一切事物
)。英文名称是
:Objectively Down
, 简称ODOWN
- 通过一定的
vote选举算法
,从剩下
的slave从服务器节点
中,选一台
提升为Master服务器节点
,然后自动修改相关配置
,并开启故障转移
(failover故障转移
)
Sentinel机制
可以解决master和slave角色
的自动切换问题
,但单点Master
的性能瓶颈
问题无法解决
,类似于MySQL
中的MHA功能
Redis Sentinel
中的Sentinel节点个数
应该为大于等于3
且最好为奇数
哨兵机制能做什么?
集群监控
:负责监控redis master和redis slave进程
是否正常工作
消息通知
:如果某个redis节点
有故障
,那么哨兵
就会发送消息
作为报警
通知给管理员
故障转移
:如果master节点
挂掉了,会自动
转移到slave节点
上配置中心
:如果故障转移
发生了,会通知client客户端
新的master地址
什么是主观下线和客观下线?
主观下线
客观下线
- 如果
被标记下线
的redis节点
是master节点
,则还需要获得其他sentinel节点
的判断
,如果超过法定数量
的投票
,就会认为该master节点不可用
,就会标记
该master节点
为客观下线
哨兵的三个定时监控
监控1
:哨兵节点
每隔10秒
向redis master和redis slave节点
发送info指令
,获取最新的拓扑结构
,并更新自身保存的节点信息
监控2
:哨兵节点
每隔2秒
向redis指定频道
上发送对master主节点状态的判断
和自身哨兵节点的信息
,其他哨兵节点
也会订阅
这个频道
,来了解对master主节点状态的判断
和自身哨兵节点的信息
监控3
:哨兵节点
每隔1秒
向redis所有节点
和其他哨兵节点
发送ping信息
,进行心跳检测
master主节点下线后,怎么进行故障转移?
- 这里主要有
2步
,首先是哨兵系统
中会进行leader角色
的选举
,再由leader哨兵
去负责故障转移
leader哨兵的选举
- 当master下线后,每个哨兵都可以选择自己作为leader,将请求发送其他哨兵
- 其他哨兵接受到请求后,可以选择同意或者不同意(根据判定基础决定)
- 如果最终某个哨兵节点获得了超过半数的投票,则该哨兵节点就会成为leader,负责故障转移
故障转移,选举新的master
过滤掉
与leader哨兵
断开连接时间
比较长
的redis节点
优先
选择replica-priority小的
- 选择
偏移量比较大
的(复制的数据越多的
) 运行id较小
的
执行故障转移
leader
向新master节点
发送slave no one
命令,让它断开与原master的连接
,成为独立节点
leader
向其他slave从节点
发送slave ip port
指令,让它向新master节点进行同步
redis_53">客户端
是和哨兵通信
还是redis集群通信
?
- 其实
都有建立通信
,情况是这样的:
client
连接集群
,首先
会连接sentinel系统
,然后订阅
相关的频道
获取redis集群主从切换,切换进度,新master地址
等信息- 拿到
master地址
后,则会与master建立连接
- 当
leader
执行了故障转移
,选举了新的master
后,也会在客户端订阅的频道
中发送
最新的master地址
client
拿到最新的master地址
后,与其建立连接
实验步骤
- 在
所有阶段
中关闭redis的安全模式
编辑sentinel.conf
protected-mode no #关闭保护模式
port 26379 #监听端口
daemonize no #前台模式
pidfile /var/run/redis-sentinel.pid #sentinel进程pid文件
loglevel notice #日志级别
logfile ""
dir /tmp
sentinel monitor mymaster 172.25.254.10 6379 2 #创建sentinel监控监控master主机,2表示必须得到2票
sentinel down-after-milliseconds mymaster 10000 #master中断时长,10秒连不上视为master下线
acllog-max-len 128
sentinel parallel-syncs mymaster 1 #发生故障转移后,每次开始同步新master数据的slave数量
sentinel failover-timeout mymaster 180000 #整个故障切换的超时时间为3分钟
sentinel deny-scripts-reconfig yes
- 所有
redis集群
都要编辑
[root@redis-node1 ~]# vim /etc/redis/sentinel.conf
sentinel monitor
:这是Redis Sentinel命令
的一部分
,用于开始监控
一个新的master主节点
mymaster
:这是你给被监控
的master主节点起
的名字
,可以是任意字符串
,但在你的Sentinel配置
中需要保持一致
。这个名字
用于在Sentinel系统内部
标识这个主节点
172.25.254.10
:这是被监控
的主节点
的IP地址
。Sentinel
会使用这个地址
来与主节点
进行通信
6379
:这是被监控
的主节点
的端口号
。Redis
默认使用6379端口
2
:这是Sentinel
判定主节点
是否客观下线
(objectively down
)所需
的Sentinel数量
(阈值
)。只有
当至少2
个Sentinel
判定主节点不可达
时,主节点
才会被认为客观下线
,并触发故障转移流程
。通常建议
设置为Sentinel总数
的半数以上
,以确保判断
的可靠性
sentinel down-after-milliseconds mymaster 10000
这条命令用于配置Redis Sentinel
对名为mymaster
的主节点
的故障检测时间
。具体来说,它定义了Sentinel
在多长时间内
无法从主节点
接收到有效回复后
,会将该主节点
标记为主观下线
(subjectively down
)
10000
:这是超时时间的值
,单位
为毫秒
。在这个例子
中,它被设置为10000毫秒
,即10秒
#将sentinel.conf发给node2
[root@redis-node1 ~]# scp /etc/redis/sentinel.conf root@172.25.254.20:/etc/redis/
#将sentinel.conf发给node3
[root@redis-node1 ~]# scp /etc/redis/sentinel.conf root@172.25.254.30:/etc/redis/
做sentinel.conf.bak备份
[root@redis-node1 ~]# cp /etc/redis/sentinel.conf /etc/redis/sentinel.conf.bak
[root@redis-node2 ~]# cp /etc/redis/sentinel.conf /etc/redis/sentinel.conf.bak
[root@redis-node3 ~]# cp /etc/redis/sentinel.conf /etc/redis/sentinel.conf.bak
开启哨兵
- 所有
redis集群
都开启哨兵模式
[root@redis-node1 ~]# redis-sentinel /etc/redis/sentinel.conf
- 以上为
前台启动
,如果想后台启动
,则可以将sentinel.conf
中的daemonize
设置为yes
#查看生成的配置
[root@redis-node1 ~]# vim /etc/redis/sentinel.conf
[root@redis-node2 ~]# redis-sentinel /etc/redis/sentinel.conf
[root@redis-node3 ~]# redis-sentinel /etc/redis/sentinel.conf
测试
- 将
master
节点下线
[root@redis-node1 ~]# redis-cli shutdown
- 我们发现
node2
成为master
- 上
node1
上线
[root@redis-node1 ~]# /etc/init.d/redis_6379 start
node1上线
后自动成为slave
,然后会删除
自己原来的所有数据
,再去同步新master上的数据
- 先关闭
sentinel进程
,在将之前备份的bak文件
复制回来
#先关闭sentinel进程,在将之前备份的bak文件复制回来
[root@redis-node1 ~]# cp /etc/redis/sentinel.conf.bak /etc/redis/sentinel.conf
- 虽然
关闭
了sentinel进程
,但是新master
还是node2
#先关闭sentinel进程,在将之前备份的bak文件复制回来
[root@redis-node2 ~]# cp /etc/redis/sentinel.conf.bak /etc/redis/sentinel.conf
#先关闭sentinel进程,在将之前备份的bak文件复制回来
[root@redis-node3 ~]# cp /etc/redis/sentinel.conf.bak /etc/redis/sentinel.conf
- 重新启动
sentinel进程
[root@redis-node1 ~]# redis-sentinel /etc/redis/sentinel.conf
[root@redis-node2 ~]# redis-sentinel /etc/redis/sentinel.conf
[root@redis-node3 ~]# redis-sentinel /etc/redis/sentinel.conf
- 所以只要
node2不挂掉
,那node2
永远都是master
在整个哨兵
和主从架构
中可能会出现的问题
问题:
- 在
生产环境
中如果master和slave中
的网络
出现故障
,由于哨兵的存在
会把master提出去
,当网络恢复后
,master
发现环境发生改变
,master
就会把自己的身份
转换成slave
,master变成slave后
会把网络故障那段时间
写入自己中的数据
清掉,这样数据就丢失了
解决:
master
在被写入数据
时会持续连接slave
,mater
确保至少有2个slave
,才允许写入
,如果slave数量少于2个
,便拒绝写入
临时设定
(重启redis后会失效
)
#在master中设定
[root@redis-node2 ~]# redis-cli
127.0.0.1:6379> config set min-slaves-to-write 2
127.0.0.1:6379> config get min-slaves-to-write
1) "min-slaves-to-write"
2) "2"
永久配置
#修改master的配置文件,添加一行就行
[root@redis-node2 ~]# vim /etc/redis/6379.conf
min-slaves-to-write 2
#重启redis,不会影响master
[root@redis-node2 ~]# /etc/init.d/redis_6379 restart
127.0.0.1:6379> config get min-slaves-to-write
1) "min-slaves-to-write"
2) "2"
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
min_slaves_good_slaves:2
slave0:ip=172.25.254.30,port=6379,state=online,offset=290343,lag=1
slave1:ip=172.25.254.10,port=6379,state=online,offset=290343,lag=1
master_failover_state:no-failover
master_replid:96ab7241c9b4b11a1eff2b5eb86df14d5e3b38e7
master_replid2:fc90c49e90a38305862dd41717797f3baca3f8aa
master_repl_offset:290343
second_repl_offset:290288
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:290288
repl_backlog_histlen:56