Redis核心技术与实战【学习笔记】 - 24.Redis 脑裂

简述

所谓脑裂,就是指在主从集群中,同时有两个主节点,它们都能接收写请求。而脑裂最直接的影响就是客户端不知道该往哪个主节点写入数据,结果就是不同的客户端会往不同的主机诶点上写入数据。而且,严重的话,脑裂会导致数据丢失。

在使用主从集群时,曾遇到过这样一个问题:主从集群有 1 个主库、5 个从库和 3 个哨兵实例,在使用过程中,发现客户端发送的一些数据丢失了,这直接影响了业务层的数据可靠性。
通过一系列的问题排查,我们才知道,这其实是主从集群中的脑裂问题导致的。


1.为什么会发生脑裂?

第一步:确认是不是数据同步出现了问题

在主从集群中发生数据丢失,最常见的原因是主库的数据还没有同步到从路,结果主库发生了故障,等从库升级为主库后,未同步的数据就丢失了。

如下图所示,新写入的 a:1、b:3 ,就是因为主库故障前未同步到从库而丢失了。
在这里插入图片描述
在这种情况的数据丢失,我们可以通过比对主从库上的复制进度差值来进行判断,也就是计算 master_repl_offset 和 slave_repl_offset 的差值。如果从库上的 slave_repl_offset 小于原主库的 master_repl_offset ,那么,我们就可以认为数据丢失是由于数据同步未完成就宕机导致的。

我们在部署主从集群时,也监测了主库上的 master_repl_offset ,及从库上的 slave_repl_offset 。但是,发现数据丢失后,我们检查了新主库升级前的 slave_repl_offset ,以及原主库的 master_repl_offset,它们是一致的,也就是说,这个升级为新主库的从库,在升级时已经和原主库的数据保持一致了。那么,为什么会出现客户端发送的数据丢失呢?

分析到这里,第一个设想被推翻了。这是,又想到所有的数据操作都是客户端发送的,那么是不是可以从客户端操作日志中发现问题呢?

第二步:排查客户端的操作日志,发现脑裂现象

在排查客户端的操作日志时,发现,在主从库切换的一段时间内,有一个客户端仍然在和原主库通信,并没有和升级的新主库进行交互。这就相当于主从集群中同时有了两个主库。根据这个迹象,我们就想到了在分布式主从集群发生故障时会出现的一个问题:脑裂。

但是,不同客户端给两个逐鹿发送数据写操作,按道理来说,只会导致新数据会分布在不同的主库上,并不会造成数据丢失。那么,为什么数据仍然丢失了呢?

到这里,我们的排查思路有一次终端了。不过,在分析问题时,“从原理出发”是追本溯源的好方法。脑裂是发生在主从切换过程中,所以把研究方向投向了主从切换的执行过程。

第三步:发现是原主库虚假故障导致的脑裂

我们是采用哨兵机制进行主从切换的,当主从切换发生时,一定是有超过预设数量(quorum)的哨兵实例和主库的心跳多超时了,才会把主库判断为客观下乡,然后,哨兵开始执行切换操作。哨兵切换完成后,客户端会和新主库进行通信,发送请求操作。

但是在切换过程中,既然客户端仍然是和原主库通信,这就表明,原主库并没有真的发生故障(例如主库进程挂掉)。猜测主库是由于某些原因无法处理请求,也没有响应哨兵的心跳,才被哨兵错误地判断为客观下线的。结果,在被判断下线后,原主库又重新开始处理请求了,而此时,哨兵还没有完成主从切换,客户端仍然可以和原主库通信,客户端发送的写请求就会在原主库上写入数据了。

为了验证原主库只是假故障,我们也查看了原主库所在服务器的资源使用监控记录。

的确,我们看到原主库所在的一段时间的 CPU 利用率突然特别高,这是我们在机器上部署的一个数据采集程序导致的。因为这个程序基本上把机器的 CPU 都用满了,导致 Redis 主库无法响应心跳了,这个期间,哨兵就把主库判断为客观下乡,开始主从切换了。不过,这个数据采集程序很快恢复正常,CPU 的使用率也降下来了。此时,原主库又开始正常服务请求了。

正是因为原主库并没有真的故障,在客户端操作日志中就看到了和原主库的通信记录。等到从库被升级为新主库后,主从集群里就有了两个主库,到这里,脑裂的原因就摸清楚了。

在这里插入图片描述

2.为什么脑裂会导致数据丢失?

主从库切换后,从库一旦升级为新主库,哨兵就会让原从库执行 slave of 命令,和新主库重新进行全量同步。而在全量同步执行的最后阶段,原主库需要清空本地的数据,加载新主库发送的 RDB 文件,这样一来,原主库在主从切换期间保存的新写数据就丢失了。
在这里插入图片描述
到这里,我们就完全弄明白了这个问题的发生过程和原因。

主从切换的过程中,如果原主库只是假故障,它会触发哨兵启动主从切换,一旦等它从假故障中恢复后,又开始处理请求,这样一来,就会和新主库同时存在,形成脑裂。等到哨兵让原主库和新主库做全量同步后,原主库在切换期间保存的数据就丢失了。

3.如何应对脑裂

刚刚说了,主从集群中的数据丢失事件,归根接地是因为发生了脑裂。所以,必须找到脑裂问题的策略。

既然问题是出现在原主库发生假故障后仍然能接收请求上,我们就开始在主从集群机制的配置项中查找是否有限制主库接收请求的设置。

Redis 提供了两个配置项来限制主库的请求处理,分别是 min-slaves-to-writemax-slaves-max-lag

  • min-slaves-to-write:设置主库能进行数据同步的最少数据量
    * max-slaves-max-lag:设置了主从库间进行数据复制时,从库给主库发送 ACK 消息的最大演出(以秒为单位)

可以把 min-slaves-to-writemax-slaves-max-lag 搭配起来使用,分别给它们设置一定的阈值,假设为 N 和 T。这两个配置项组合后的要求是,主库连接的从库中至少有 N 个从库,和主库进行数据复制时的 ACK 消息延迟不能超过 T 秒,否则,主路就不会在接收客户端的请求了

即使,原主库是假故障,它在假故障期间也无法响应哨兵心跳,也不能和从库进行同步,自然也就无法和从库进行 ACK 确认了。这样一来, min-slaves-to-writemax-slaves-max-lag 的组合要求就无法得到满足,原主库就会被限制接收客户端的请求,客户端也就不能在原主库中写入数据了。

等到新主库上线时,就只有新主库能接收和处理客户端的请求,此时,新写的数据会被直接写到新主库中。而原主库会被哨兵降为从库,即使它的数据被清空了,也不会有新数据丢失。

再来举个例子。
假设我们将 min-slaves-to-write 设置为 1,把 max-slaves-max-lag 设置为 12 s,把哨兵的 down-after-milliseconds 设置为 10s,主库因为某些原因卡主了 15s,导致哨兵判断客观下线,开始进行主从切换。同时,因为原主库卡主了 15s,没有一个从库能和原主库在 12s 内进行数据复制,原主库也无法收到客户端的请求了。这样一来,主从切换完成后,只有新主库可以接受请求,不会发生脑裂。

小结

脑裂是指在主从集群中,同时有2个主库都能接收写请求。在 Redis 切换过程中,如果发生了脑裂,客户端数据就会写入到原主库,原主库被降为从库,这些新写入的数据就丢失了。

脑裂发生的原因主要是原主库发生了假故障,总结下假故障的原因:

  1. 和主库部署在同一台服务器上的其他程序临时占用了大量资源(例如 CPU 资源),导致主库资源使用受限,短时间内无法响应心跳。其他程序不再使用资源时,主库又恢复正常。
  2. 主库自身遇到了阻塞的情况,例如,处理 bigkey 或是发送内存 swap(可以复习下《11.响应延迟的波动问题及解决方案》总结的导致实例阻塞的原因),短时间内无法响应心跳,导致阻塞解除后,又恢复正常的请求处理了。

为了应对脑裂,你可以在主从集群部署时,通过合理地配置参数 min-slaves-to-writemax-slaves-max-lag ,来预防脑裂的发生。

给你的建议是,假设从库有 N 个,可以将 min-slaves-to-write 设置为 K/2 + 1(如果 K 为 1 ,就设为1),将 max-slaves-max-lag 设置为十几秒(例如 10~20 秒),在这个配置下,如果有一半以上的从库和主库进行 ACK 消息延迟超过十几秒,就会进制主库接收客户端写请求。

这样一来,就可以避免脑裂带来的数据丢失问题,而且,也不会因为只有少数几个从库因为网络阻塞连不上主库,就进制主库接收请求了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/668601.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从零开始手写mmo游戏从框架到爆炸(三)— 服务启动接口与网络事件监听器

上一章我们完成了netty服务启动的相关抽象(https://blog.csdn.net/money9sun/article/details/136025471),这一章我们再新增一个全局的服务启动类,方便后续扩展。 服务启动 新增的两个类如下: 定义一个接口IServer …

Elasticsearch:使用 Inference API 进行语义搜索

在我之前的文章 “Elastic Search 8.12:让 Lucene 更快,让开发人员更快”,我有提到 Inference API。这些功能的核心部分始终是灵活的第三方模型管理,使客户能够利用当今市场上下载最多的向量数据库及其选择的转换器模型。在今天的…

框架学习Maven

声明:本文来源于黑马程序员PDF讲义 做为一名Java开发工程师,后端 Web开发技术是我们学习的重点,后端Web开发技术的学习,我们会先学习Java项目的构建工具:Maven 初识Maven Maven是Apache旗下的一个开源项目&#xff…

Verilog实现2进制码与BCD码的互相转换

1、什么是BCD码? BCD码是一种2进制的数字编码形式,用4位2进制数来表示1位10进制中的0~9这10个数。这种编码技术,最常用于会计系统的设计里,因为会计制度经常需要对很长的数字做准确的计算。相对于一般的浮点式记数法,…

2019年江苏省职教高考计算机技能考试——一道程序改错题的分析

题目:函数将str字符串中的5个数字字符串转换为整数,并保存在二维数组m的最后一行,各元素为3、-4、16、18、6。并经函数move处理后,运行结果如下: 18 6 3 -4 16 16 18 6 3 -4 -4 16 …

香港倾斜模型3DTiles数据漫游

谷歌地球全香港地区倾斜摄影数据,通过工具转换成3DTiles格式,将这份数据完美加载到三维数字地球Cesium上进行完美呈现,打造香港地区三维倾斜数据覆盖,完美呈现香港城市壮美以及维多利亚港繁荣景象。再由12.5米高分辨率地形数据&am…

【开源】JAVA+Vue+SpringBoot实现二手车交易系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 二手车档案管理模块2.3 车辆预约管理模块2.4 车辆预定管理模块2.5 车辆留言板管理模块2.6 车辆资讯管理模块 三、系统设计3.1 E-R图设计3.2 可行性分析3.2.1 技术可行性分析3.2.2 操作可行性3.2.3 经济…

02.05

1.单链表 main #include "1list_head.h" int main(int argc, const char *argv[]) { //创建链表之前链表为空Linklist headNULL;int n;datatype element;printf("please enter n:");scanf("%d",&n);for(int i0;i<n;i){printf("ple…

IDEA新建文件夹后右击不能创建class类排错方法

目录 1 查看自身文件名是否为关键词 2 查看是否被“蓝色文件夹”给包含了 3 检查设置那边的class模板 4 报错解决 1 查看自身文件名是否为关键词 如下使用了 Java中的关键词"class"所以才无法创建包 ---------------------------------------------------------…

量化交易学习4(投资组合基本认识)

1 如何衡量投资组合的收益率 1.1 投资组合收益率的计算方法 1.2 投资组合的绝对收益率和相对收益率 2 如何衡量投资组合的风险 2.1 风险的定义 风险是指在未来可能发生的不确定性事件所带来的潜在损失。 在投资领域中&#xff0c;风险通常指投资所面临的不确定性和潜在的损失…

自学Python第二十二天- Django框架(六) django的实用插件:cron、APScheduler

django-crontab 和 django-cron 有时候需要django在后台不断的执行一个任务&#xff0c;简单的可以通过中间件来实现&#xff0c;但是中间件是根据请求触发的。如果需要定时执行任务&#xff0c;则需要使用到一些插件。 django-crontab 和 django-cron 是常用的用于处理定时任…

群晖NAS开启FTP服务结合内网穿透实现公网远程访问本地服务

⛳️ 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 文章目录 ⛳️ 推荐1. 群晖安装Cpolar2. 创建FTP公网地址3. 开启群晖FTP服务4. 群晖FTP远程连接5. 固定FTP公网地址6. 固定FTP…

【优先级队列(大顶堆 小顶堆)】【遍历哈希表键值对】Leetcode 347 前K个高频元素

【优先级队列&#xff08;大顶堆 小顶堆&#xff09;】【排序】Leetcode 347 前K个高频元素 1.不同排序法归纳2.大顶堆和小顶堆3.PriorityQueue操作4.PriorityQueue的升序&#xff08;默认&#xff09;与降序5.问题解决&#xff1a;找前K个最大的元素 &#xff1a;踢走最小的&…

HashCat 恢复Excel、Word、PPT密码保姆教程

HashCat 恢复Excel、Word、PPT密码 一、流程 整体需要两个步骤 先用office2john.py获取下文件的hash值 python office2john.py 1.xlsx > hash这个命令需要你电脑有python环境&#xff0c;然后在cmd命令窗口中执行此命令就行 文件链接&#xff1a;https://github.com/magnu…

Python 轻量级定时任务调度:APScheduler

简述 APscheduler (Advanced Python Scheduler)&#xff0c;作用为按指定的时间规则执行指定的作业。提供了基于日期date、固定时间间隔interval 、以及类似于Linux上的定时任务crontab类型的定时任务。该框架不仅可以添加、删除定时任务&#xff0c;还可以将任务存储到数据库…

Linux内核编译-ARM

步骤一、下载源码及交叉编译器后解压 linux kernel官网 ARM GCC交叉编译器 步骤二、安装软件 sudo apt-get install ncurses-dev sudo apt-get install flex sudo apt-get install bison sudo apt install libgtk2.0-dev libglib2.0-dev libglade2-dev sudo apt install libs…

使用useRoutes提示invalid hook call

包版本&#xff1a; 问题&#xff1a; 今天用vitereactts重新搭建项目时报错 代码&#xff1a; router.tsx import { useRoutes } from react-router-dom; import Home from "../pages/home/index";const routers[{path: /,element: <Home/> } ] // const…

jmeter设置关联

一、为什么要设置关联&#xff1f; http协议本身是无状态的&#xff0c;客户端只需要简单向服务器请求下载某些文件&#xff0c;无论是客户端还是服务端都不去记录彼此过去的行为&#xff0c;每一次请求之间都是独立的。如果jmeter需要设置跨线程组脚本&#xff0c;就必须设置…

【LeetCode: 292. Nim 游戏+ 博弈问题】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

MySQL 小技巧:xtrabackup 软件包的下载及安装

案例&#xff1a;xtrabackup 软件包的下载及安装 软件包下载&#xff1a;Index of /percona/centos/7/RPMS/x86_64/ CentOS7 默认的数据库版本比较老,因此建议使用 xtrabackup 2.4 版本 // CentOS7 默认的数据库版本比较老,因此建议使用 xtrabackup 2.4 版本 // 安装 CentOS7 默…