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)
相关推荐
小吴编程之路5 小时前
MySQL 索引核心特性深度解析:从底层原理到实操应用
数据库·mysql
~莫子5 小时前
MySQL集群技术
数据库·mysql
凤山老林5 小时前
SpringBoot 使用 H2 文本数据库构建轻量级应用
java·数据库·spring boot·后端
就不掉头发6 小时前
Linux与数据库进阶
数据库
与衫6 小时前
Gudu SQL Omni 技术深度解析
数据库·sql
咖啡の猫6 小时前
Redis桌面客户端
数据库·redis·缓存
oradh6 小时前
Oracle 11g数据库软件和数据库静默安装
数据库·oracle
what丶k6 小时前
如何保证 Redis 与 MySQL 数据一致性?后端必备实践指南
数据库·redis·mysql
_半夏曲6 小时前
PostgreSQL 13、14、15 区别
数据库·postgresql
把你毕设抢过来6 小时前
基于Spring Boot的社区智慧养老监护管理平台(源码+文档)
数据库·spring boot·后端