Redis主从复制架构和Sentinel哨兵机制
Redis专题地址:https://www.cnblogs.com/hello-shf/category/1615909.html
SpringBoot读源码系列:https://www.cnblogs.com/hello-shf/category/1456313.html
Elasticsearch系列:https://www.cnblogs.com/hello-shf/category/1550315.html
数据结构系列:https://www.cnblogs.com/hello-shf/category/1519192.html
一、redis主从复制原理
redis主从同步策略:slave刚加入集群会触发一次全量同步(全量复制)。全量同步之后,进行增量复制。slave优先是增量同步,如果增量同步失败会尝试从master节点进行全量复制。
全量复制:slave初始化阶段

如上图
- slave服务器首先连接master节点,发送SYNC命令。
 - master节点收到SYNC命令开始指令BGSAVE(延迟写,读正常)命令生成RDB(快照)文件,在此期间master的写请求会被缓存。
 - RDB生成,master会将该RDB发送给所有的slave。
 - slave收到RDB文件会抛弃之前的旧数据,然后载入新的RDB。
 - master完成RDB发送,会执行之前阻塞的写命令,并将这些命令同步到slave节点。(增量复制)
 - 以上步骤完成后master和slave开始正常工作。
 
值得注意的是,全量复制对主从都是非阻塞的,是异步复制。
增量复制:master每次的写命令会同步到slave,slave收到命令执行对应命令。
断点续传:在步骤3步骤中,master发送给slave的文件过程中,网络故障了,重连后,master仅会复制给slave缺少的部分(会记录offset偏移量)。
master node 会在内存中维护一个 backlog,master 和 slave 都会保存一个 replica offset 还有一个 master run id,offset 就是保存在 backlog 中的。如果 master 和 slave 网络连接断掉了,slave 会让 master 从上次 replica offset 开始继续复制,如果没有找到对应的 offset,那么就会执行一次 resynchronization。
主从复制中的内存淘汰策略:slave不会主动淘汰过期key,master处理掉的过期key,会向slave发送一个del命令,同步淘汰的数据。
心跳数据:master 默认每隔 10秒 发送一次 heartbeat,slave node 每隔 1秒 发送一个 heartbeat。
注意,如果采用了主从架构,那么建议必须开启 master node 的持久化,不建议用 slave node 作为 master node 的数据热备,因为那样的话,如果你关掉 master 的持久化,可能在 master 宕机重启的时候数据是空的,然后可能一经过复制, slave node 的数据也丢了。
另外,master 的各种备份方案,也需要做。万一本地的所有文件丢失了,从备份中挑选一份 rdb 去恢复 master,这样才能确保启动的时候,是有数据的,即使采用了高可用机制,slave node 可以自动接管 master node,但也可能 sentinel 还没检测到 master failure,master node 就自动重启了,还是可能导致上面所有的 slave node 数据被清空。
二、哨兵机制
哨兵之前的主从架构是需要在各自的配置文件中手动配置自己的master或者slave节点。(方便理解后面的Configuration传播)
假如采用了redis的主从方案,那么当master节点宕机,主备切换的过程是需要运维人员手动完成的,人工的故障转移是十分的耗时而且对运维人员的要求是极高的。
所以就有了基于redis哨兵(Sentinel)机制搭建的高可用架构。
1,sentinel
中文哨兵。哨兵是 redis 集群机构中非常重要的一个组件,主要有以下功能:
- 集群监控:负责监控 redis master 和 slave 进程是否正常工作。
 - 消息通知:如果某个 redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
 - 故障转移:如果 master node 挂掉了,会自动转移到 slave node 上。
 - 配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址。
 
哨兵用于实现 redis 集群的高可用,本身也是分布式的,作为一个哨兵集群去运行,互相协同工作。
- 故障转移时,判断一个 master node 是否宕机了,需要大部分的哨兵都同意才行,涉及到了分布式选举的问题。
 - 即使部分哨兵节点挂掉了,哨兵集群还是能正常工作的,因为如果一个作为高可用机制重要组成部分的故障转移系统本身是单点的,那就很坑爹了。
 
2,核心知识
- 哨兵至少需要 3 个实例,来保证自己的健壮性。
 - 哨兵 + redis 主从的部署架构,是不保证数据零丢失的,只能保证 redis 集群的高可用性。
 - 对于哨兵 + redis 主从这种复杂的部署架构,尽量在测试环境和生产环境,都进行充足的测试和演练。
 
3,故障转移
- sdown 是主观宕机,就一个哨兵如果自己觉得一个 master 宕机了,那么就是主观宕机
 - odown 是客观宕机,如果 quorum 数量的哨兵都觉得一个 master 宕机了,那么就是客观宕机
 
sdown 达成的条件很简单,如果一个哨兵 ping 一个 master,超过了 is-master-down-after-milliseconds 指定的毫秒数之后,就主观认为 master 宕机了;如果一个哨兵在指定时间内,收到了 quorum 数量的其它哨兵也认为那个 master 是 sdown 的,那么就认为是 odown 了。
三、slave->master 选举算法
如果一个 master 被认为 odown 了,而且 majority 数量的哨兵都允许主备切换,那么某个哨兵就会执行主备切换操作,此时首先要选举一个 slave 来,会考虑 slave 的一些信息:
- 跟 master 断开连接的时长
 - slave 优先级
 - 复制 offset
 - run id
 
如果一个 slave 跟 master 断开连接的时间已经超过了 down-after-milliseconds 的 10 倍,外加 master 宕机的时长,那么 slave 就被认为不适合选举为 master。
(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state
接下来会对 slave 进行排序:
- 按照 slave 优先级进行排序,slave priority 越低,优先级就越高。
 - 如果 slave priority 相同,那么看 replica offset,哪个 slave 复制了越多的数据,offset 越靠后,优先级就越高。
 - 如果上面两个条件都相同,那么选择一个 run id 比较小的那个 slave。
 
quorum 和 majority:
每次一个哨兵要做主备切换,首先需要 quorum 数量的哨兵认为 odown,然后选举出一个哨兵来做切换,这个哨兵还需要得到 majority 哨兵的授权,才能正式执行切换。
如果 quorum < majority,比如 5 个哨兵,majority 就是 3,quorum 设置为 2,那么就 3 个哨兵授权就可以执行切换。
但是如果 quorum >= majority,那么必须 quorum 数量的哨兵都授权,比如 5 个哨兵,quorum 是 5,那么必须 5 个哨兵都同意授权,才能执行切换。
主备切换带来的数据丢失问题
数据丢失的两种情况:
- 异步复制导致的数据丢失
 
因为 master->slave 的复制是异步的,所以可能有部分数据还没复制到 slave,master 就宕机了,此时这部分数据就丢失了。
- 脑裂导致的数据丢失
 
脑裂,也就是说,某个 master 所在机器突然脱离了正常的网络,跟其他 slave 机器不能连接,但是实际上 master 还运行着。此时哨兵可能就会认为 master 宕机了,然后开启选举,将其他 slave 切换成了 master。这个时候,集群里就会有两个 master ,也就是所谓的脑裂。
此时虽然某个 slave 被切换成了 master,但是可能 client 还没来得及切换到新的 master,还继续向旧 master 写数据。因此旧 master 再次恢复的时候,会被作为一个 slave 挂到新的 master 上去,自己的数据会清空,重新从新的 master 复制数据。而新的 master 并没有后来 client 写入的数据,因此,这部分数据也就丢失了。
解决方案:
进行如下配置:
min-slaves-to-write 1
min-slaves-max-lag 10
表示,要求至少有 1 个 slave,数据复制和同步的延迟不能超过 10 秒。
如果说一旦所有的 slave,数据复制和同步的延迟都超过了 10 秒钟,那么这个时候,master 就不会再接收任何请求了。
- 减少异步复制数据的丢失
 
有了 min-slaves-max-lag 这个配置,就可以确保说,一旦 slave 复制数据和 ack 延时太长,就认为可能 master 宕机后损失的数据太多了,那么就拒绝写请求,这样可以把 master 宕机时由于部分数据未同步到 slave 导致的数据丢失降低的可控范围内。
- 减少脑裂的数据丢失
 
如果一个 master 出现了脑裂,跟其他 slave 丢了连接,那么上面两个配置可以确保说,如果不能继续给指定数量的 slave 发送数据,而且 slave 超过 10 秒没有给自己 ack 消息,那么就直接拒绝客户端的写请求。因此在脑裂场景下,最多就丢失 10 秒的数据。
四、哨兵集群的自动发现机制
哨兵互相之间的发现,是通过 redis 的 pub/sub 系统实现的,每个哨兵都会往 __sentinel__:hello 这个 channel 里发送一个消息,这时候所有其他哨兵都可以消费到这个消息,并感知到其他的哨兵的存在。
每隔两秒钟,每个哨兵都会往自己监控的某个 master+slaves 对应的 __sentinel__:hello channel 里发送一个消息,内容是自己的 host、ip 和 runid 还有对这个 master 的监控配置。
每个哨兵也会去监听自己监控的每个 master+slaves 对应的 __sentinel__:hello channel,然后去感知到同样在监听这个 master+slaves 的其他哨兵的存在。
每个哨兵还会跟其他哨兵交换对 master 的监控配置,互相进行监控配置的同步。
五、configuration 传播
哨兵完成切换之后,会在自己本地更新生成最新的 master 配置,然后同步给其他的哨兵,就是通过之前说的 pub/sub 消息机制。
这里之前的 version 号就很重要了,因为各种消息都是通过一个 channel 去发布和监听的,所以一个哨兵完成一次新的切换之后,新的 master 配置是跟着新的 version 号的。其他的哨兵都是根据版本号的大小来更新自己的 master 配置的。
参考文献:
  https://github.com/hello-shf/advanced-java
  https://www.cnblogs.com/daofaziran/p/10978628.html
  如有错误的地方还请留言指正。
  原创不易,转载请注明原文地址:https://www.cnblogs.com/hello-shf/p/12072330.html
Redis主从复制架构和Sentinel哨兵机制的更多相关文章
- Redis的主从复制与Redis Sentinel哨兵机制
		
1 Redis的主从复制 1.1 什么是主从复制 持久化保证了即使redis服务重启也不会丢失数据,因为redis服务重启后会将硬盘上持久化的数据恢复到内存中,但是当redis服务器的硬盘损 ...
 - Redis事务,持久化,哨兵机制
		
1 Redis事务 基本事务指令 Redis提供了一定的事务支持,可以保证一组操作原子执行不被打断,但是如果执行中出现错误,事务不能回滚,Redis未提供回滚支持. multi 开启事务 exec 执 ...
 - Redis主从架构搭建和哨兵模式(四)
		
一主一从,往主节点去写,在从节点去读,可以读到,主从架构就搭建成功了 1.启用复制,部署slave node wget http://downloads.sourceforge.net/tcl/tcl ...
 - Redis主从复制(Master/Slave) 与哨兵模式
		
Redis主从复制是什么? 行话:也就是我们所说的主从复制,主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主 Redis主从复制 ...
 - NoSQL初探之人人都爱Redis:(4)Redis主从复制架构初步探索
		
一.主从复制架构简介 通过前面几篇的介绍中,我们都是在单机上使用Redis进行相关的实践操作,从本篇起,我们将初步探索一下Redis的集群,而集群中最经典的架构便是主从复制架构.那么,我们首先来了解一 ...
 - 【转】 NoSQL初探之人人都爱Redis:(4)Redis主从复制架构初步探索
		
一.主从复制架构简介 通过前面几篇的介绍中,我们都是在单机上使用Redis进行相关的实践操作,从本篇起,我们将初步探索一下Redis的集群,而集群中最经典的架构便是主从复制架构.那么,我们首先来了解一 ...
 - redis高可用之sentinel哨兵
		
一,单实例模式 当系统中只有一台redis运行时,一旦该redis挂了,会导致整个系统无法运行. 二,主从模式 由于单台redis出现单点故障,就会导致整个系统不可用,所以想到的办法自然就是备份.当一 ...
 - Redis | 第12章 Sentinel 哨兵模式《Redis设计与实现》
		
目录 前言 1. 启动并初始化 Sentinel 2. Sentinel 与服务器间的默认通信 2.1 获取主服务器信息 2.2 获取从服务器信息 2.3 向主服务器和从服务器发送信息 3. 接受来自 ...
 - redis缓存架构-02-两种持久化机制(RDB和AOF)
		
1.两种持久化机制的介绍 1.1 RDB 周期性的生成redis内存数据的一份完整的快照 1)根据配置的检查点,生产rdb快照文件,fork一个子线程,将数据dump到rdb快照文件中,完成rdb文件 ...
 
随机推荐
- objc反汇编分析__strong和__weak
			
如题所说反汇编看__strong和__weak的真实样子,代码列举自然多,篇幅长不利于阅读,我就先搬出结论,后面是分析. 在NON-ARC环境,__strong和__weak不起作用.相反在ARC环境 ...
 - python 学习路程(一)
			
好早之前就一直想学python,可是一直没有系统的学习过,给自己立个flag,从今天开始一步步掌握python的用法: python是一种脚本形式的语言,据说是面向废程序员学习开发使用的,我觉得很适合 ...
 - vue监听移动设备的返回事件
			
在公共方法文件common.js中实现一个存储当前历史记录的方法 common.js // 存储当前历史记录点,实现控制手机物理返回键的按钮事件 var pushHistory = function ...
 - 【Luogu P1168】【Luogu P1801&UVA 501】中位数&黑匣子(Black Box)——对顶堆相关
			
Luogu P1168 Luogu P1801 UVA 501(洛谷Remote Judge) 前置知识:堆.优先队列STL的使用 对顶堆 是一种在线维护第\(k\)小的算法. 其实就是开两个堆,一个 ...
 - 为什么服务器突然回复RST——小心网络中的安全设备
			
RST产生原因 一般情况下导致TCP发送RST报文的原因有如下3种: 1. SYN数据段指定的目的端口处没有接收进程在等待. 2.TCP想放弃一个已经存在的连接. 3.TCP ...
 - NIO-概览
			
目录 NIO-概览 目录 前言 什么是NIO 通道 缓冲区 选择器 其他 管道 FileLock 参考文档 NIO-概览 目录 NIO-概览 前言 本来是想学习Netty的,但是Netty是一个NIO ...
 - linux中安装tensorflow
			
liunxsudo apt-get install python-pip python-dev python2.X -> pippython3.X -> pip3 pip --versio ...
 - Android DataBinding不能自动生成ViewDataBinding类的解决方法
			
如果Build.gradle和Layout文件配置正确,仍无法生成ViewDataBinding类. 经测试,Gradle的sync无效,clean project无效,invalidate and ...
 - php踩过的那些坑(3) 数据类型转换
			
一.前方有坑 php属于弱类型语言,不会强迫工程师在使用变量之前先声明变量类型,开发时爽了,但是也带来不少的坑.下面就举一个坑的例子: 例1: $str = ‘haodaquan'; echo ($s ...
 - 区块链学习笔记:DAY05 如何使用公有云区块链服务
			
这是最后一节课了,主要讲华为云在云区块链提供的服务,如何基于华为云BCS来构建应用 先来个简单的比喻: 1.有关BaaS的范围定义 包含物理主机.虚拟主机.容器服务.区块链.智能合约和服务 2.华为云 ...