redis--------哨兵模式

1.哨兵模式

试想一下,如果主从模式中,大半夜主节点挂了,运维从床上迷迷糊糊爬起来,打开电脑,手动升级处理,怕不是第二天就要上头条了。

哨兵模式的出现用于解决主从模式中无法自动升级主节点的问题,一个哨兵是一个节点,用于监控主从节点的健康,当主节点挂掉的时候,自动选择一个最优从节点升级为主节点。

但哨兵如果挂了怎么办?于是哨兵一般都会是一个集群,是集群高可用的心脏,一般由3-5个节点组成,即使个别节点挂了,集群还可以正常运行。

优点

  • 可以在master挂掉后自动选举新的master

缺点

  • master挂了,切换新的master会造成未来得及主从同步的数据丢失
  • 大数据高并发,单个master内存仍存在上限
  • 主从全量同步仍然要耗费大量时间
  • 单个Redis只能利用CPU的单个核心,应对海量数据捉襟见肘

解决办法

  • Redis集群方案

客户端连接Redis,会首先连接Sentinel,通过Sentinel查询master地址,然后再连接master进行数据交互。当master挂了,客户端重新跟Sentinel要master地址,连接新的master。

上图中可看,master挂了,原先的主从复制断开,客户端和master也断开。然后一个slave变成新的master,和其余的slave进行新的主从复制,客户端通过新的master继续交互,Sentinel持续监控已经挂掉的旧的master,一旦旧的master恢复,集群会变为下图,旧的master成为新的slave,从新的master建立主从复制关系。

2.哨兵模式的工作机制

  • 一个Sentinel或Sentinel集群可以管理多个主从Redis,如果只有一个Redis,Sentinel没有意义
  • master挂了,Sentinel在slave中选举一个升级为master,并修改配置文件
  • 挂了的master恢复后,只能当slave,跟新选举的master主从复制
  • Sentinel有可能会挂,所以Sentinel一般都是一个集群
  • 每个Sentinel节点定期检测Redis数据节点、其余Sentinel节点是否可达
  • 对于节点的故障是由多个Sentinel节点共同完成,有效防止误判
  • Redis主从复制为异步,master挂了,从节点可能会丢失一部分信息,Sentinel无法保证消息完全不丢失,但可以做到尽量少丢失
  • Sentinel.slave_for方法可以从连接池内采用轮询方案拿出一个slave地址,实现负载均衡

3.1 定时监控任务

  • 每隔10秒,每个Sentinel节点会向主节点和从节点发送info命令获取最近的拓扑结构,可以感知新加入或故障转移的Redis数据节点
  • 每隔2秒,每个Sentinel节点会与其他Sentinel节点通信,可以发现新的Sentinel节点,并与其他Sentinel节点交换对主节点的判断信息,方便故障转移及选举
  • 每隔1秒,每个Sentinel节点会向主节点、从节点以及其他的Sentinel节点发送ping做一次心跳检测,来确认这些节点是否可达,实现对每个节点的监控

3.2 主观下线和客观下线

主观下线

当Sentinel节点ping其他节点,超时未回复,Sentinel节点就会对该节点做失败判定。主观下线是当前Sentinel节点的一家之言,存在误判可能

客观下线

当Sentinel主观下线的节点是master,该Sentinel会询问其他Sentinel对master的判断,当大部分Sentinel都对master的下线做了同意判断,那么这个判断就是比较客观的

3.3 Sentinel集群的领导者选举

Sentinel节点已经对master做了客观下线,但还不能立刻进行故障转移,因为故障转移工作只需要一个Sentinel节点来完成,因此在Sentinel集群中要选出一个leader来进行故障转移。

Redis使用了Raft算法实现领导者选举:

  • 每个在线的Sentinel节点都有资格成为领导者,他要求其他节点来投自己一票
  • 先收到谁的要求就给谁投票,但不能给自己投
  • 首先拿到大多数(即一半+1)的票当选领导者

3.4 故障转移

  1. 排除主观下线的从节点
  2. 选择优先级高的从节点,如果没有再进行3
  3. 选择复制偏移量最大的从节点(复制的最完整),如果没有再进行4
  4. 选择runid最小的从节点

4. 哨兵模式的原理

1 多个sentinel发现并确认master有问题
2 选举触一个sentinel作为领导(raft算法)
3 选取一个slave作为新的master
4 通知其余slave成为新的master的slave
5 通知客户端主从变化
6 等待老的master复活成为新master的slave

哨兵:是一个进程---》启动使用redis-sentinel启动,有自己的配置文件,启动后,可以客户端连接(redis-cli),查看哨兵状态

4.1配置哨兵 (一主两从架构---》运行多个哨兵--》一般奇数个(3个))

配置哨兵配置文件:

python 复制代码
port 26379
daemonize yes
dir /root/lqz/redis-6.2.9/data
protected-mode no
bind 0.0.0.0
logfile "redis_sentinel.log"

sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
# 2 配置3个配置文件,监听端口不一样(正常应该放在3台机器上)

# 3 启动哨兵
#启动三个哨兵
./src/redis-sentinel sentinel_26379.conf
./src/redis-sentinel sentinel_26380.conf
./src/redis-sentinel sentinel_26381.conf


# 4 演示故障
	-把主库停止
  -查看自动故障切换
  -启动起原来主库,变成了从

4.2python 操作哨兵

python 复制代码
import redis
from redis.sentinel import Sentinel

# 连接哨兵服务器(主机名也可以用域名)
# 10.0.0.101:26379
sentinel = Sentinel([('8.130.125.9', 26379),
                     ('8.130.125.9', 26380),
                     ('8.130.125.9', 26381)
         ],
                    socket_timeout=5)

print(sentinel)
# 获取主服务器地址
master = sentinel.discover_master('mymaster')
print(master)

# 获取从服务器地址
slave = sentinel.discover_slaves('mymaster')
print(slave)



##### 读写分离
# 获取主服务器进行写入
master = sentinel.master_for('mymaster', socket_timeout=0.5)
w_ret = master.set('foo', 'bar')

# slave = sentinel.slave_for('mymaster', socket_timeout=0.5)
# r_ret = slave.get('foo')
# print(r_ret)
相关推荐
呆呆小雅1 分钟前
C#关键字volatile
java·redis·c#
阳冬园4 分钟前
mysql数据库 主从同步
数据库·主从同步
miss writer30 分钟前
Redis分布式锁释放锁是否必须用lua脚本?
redis·分布式·lua
Mr.131 小时前
数据库的三范式是什么?
数据库
Cachel wood1 小时前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Python之栈1 小时前
【无标题】
数据库·python·mysql
风_流沙2 小时前
java 对ElasticSearch数据库操作封装工具类(对你是否适用嘞)
java·数据库·elasticsearch
亽仒凣凣2 小时前
Windows安装Redis图文教程
数据库·windows·redis
亦世凡华、2 小时前
MySQL--》如何在MySQL中打造高效优化索引
数据库·经验分享·mysql·索引·性能分析
YashanDB2 小时前
【YashanDB知识库】Mybatis-Plus调用YashanDB怎么设置分页
数据库·yashandb·崖山数据库