一次redis主从切换导致的数据丢失与陷入只读状态故障

news2024/10/5 3:44:12

背景

最近一组业务redis数据不断增长需要扩容内存,而扩容内存则需要重启云主机,在按计划扩容升级执行主从切换时意外发生了数据丢失与master进入只读状态的故障,这里记录分享一下。

业务redis高可用架构

该组业务redis使用的是一主一从,通过sentinel集群实现故障时的自动主从切换,这套架构已经平稳运行数年,经历住了多次实战的考验。
高可用架构大体如下图所示:


简单说一下sentinel实现高可用的原理:
集群的多个(2n+1,N>1)哨兵会定期轮询redis的所有master/slave节点,如果sentinel集群中超过一半的哨兵判定redis某个节点已经主观下线,就会将其判定为客观下线进行相应处理:

  1. 如果下线节点是master,选定一个正常work的slave将其选定为新的master节点。
  2. 如果下线节点是slave,将其从slave节点中移除。

如果已经被客观下线的节点恢复了正常,sentinel中超过一半哨兵确认后则将其加回可用的slave节点。
所有需要读写redis的server并不需要直接写死redis 主从配置,而是通过访问sentinel获取当前redis的主从可用状态,具体实现方式可以定时查询sentinel询问更新,也可以通过订阅机制让sentinel在主从变动时主动通知订阅方更新。
sentinel实现高可用的详细原理这里不做过多赘述,有兴趣的小伙伴可以移步参考文献中的相关资料。

具体内存扩容流程

sentinel可以在检测到故障时自动切换redis主从,也可以主动执行sentinel failover mastername 命令实现手动切换主从,所以这次的内存扩容重启流程设计如下(A代表初始master所在云主机,B代表初始slave所在云主机):

  1. 升级主机B内存配置,重启主机B
  2. 检查B重启后其上的redis slave是否重新同步master数据完成,包括:
    2.1 查看slave redis log是否异常,无异常pass
    2.2 使用info keyspace命令check master、slave 各db key数量是否一致,无异常pass
    2.3 在master写入一个测试key,在slave上check是否同步成功
    2.4 观察依赖server log是否有异常
  3. 使用sentinel failover mastername命令手动主从切换,主机A变成新slave,主机B变成新master,根据以前手动切换的经验走到这一步基本上就稳了--因为这里本质上和一次普通主从切换已经没有区别了。
  4. 升级主机A内存配置,重启主机A,执行以下check:
    4.1 查看新slave redis log是否异常
    4.2 使用info keyspace命令check 新master、新slave 各db key数量是否一致,无异常pass
    4.3 在新master写入测试key,在新slave上check是否同步成功
    4.4 观察依赖server log是否有异常

至此,若以上步骤都正常通过,一个完美的redis内存升级工作就完成了。

主从切换后数据丢失

结果正是没有想过可能会出问题的步骤3反而出现了问题,直接导致了主从切换后丢掉了部分数据,并且新master进入只读状态将近十分钟。
当时的情况是这样的:
在执行完步骤3后,check 新slave redis log无异常,正在考虑观察一会儿后执行主机A的升级重启操作,api的分钟级别异常监控触发了一小波redis相关报警。第一反应在新master与新slave上执行了info keyspace查看key数量是否已经不一致,结果发现master/slave的key数量是一致的--但是再仔细一看:和切换前的key总数百万级相比切换后key总数降到了十万级--大部分key数据被丢失了。
查看新master、新slave log都没有发现明显log可以解释为什么主从切换后会丢失一大半数据这一现象,这时小伙伴第一次提到了是不是内存不够了,当时自己略一思考马上回复到:新master刚升级了内存,不可能内容扩大后反而内存不足的,所以应该不是这个问题。
n分钟后...
小伙伴再一次提出了是不是maxmemory问题,这一下子点中了关键点,马上想到主机B升级了内存是不会有系统层面内存不足的问题,但是redis的内存使用实际上还会受到maxmemory参数限制,马上在新master上执行config get maxmemory, 只有3GB,而升级前数据实际使用内存超过了6GB!
立刻调大了新master的maxmemory参数,redis很快恢复了可读写正常状态,一大波redis只读引发的告警通知开始快速下降。

原因定位

紧张又刺激的故障处理就这么过去了,在优先处理完丢失key数据恢复工作之后,开始回顾整理故障的详细原因,总共有如下几个疑问:

  1. 明确记得上个月给主机A、B上的redis都通过config set maxmemory设置为了7GB,为什么出现问题时查询B上redis 的maxmemory配置却变成了3GB?
  2. 如果主机B的maxmemory是3GB,其作为slave时为什么从master同步超过6GB的数据时不会有问题?--在主从切换前无论是查看info keyspace还是在master上写入测试key同步check都是OK的。
  3. 为什么主从切换后主机B上的key数据会丢失?这个是因为maxmemory设置过小,是故障的直接原因。
  4. 为什么新master由于maxmemory参数超限进入只读状态且删除部分数据后,新master中实际数据占用的大小依然超过>3GB?

如上四个疑问除了问题3已经明确了,剩下三个问题都让人疑惑--事出诡异必有妖,经过一番探寻得出其答案:

  1. 上个月修改redis maxmemory时,只通过config set命令修改了其运行时配置,而没有修改对应配置redis.conf上maxmemory的值,主机B上redis在重启后就会从redis.conf上载入该maxmemory,该配置正是3GB,同时maxmemory参数是redis节点独立的配置,slave并不会从master同步该值。
  2. 在redis5.0版本之后,redis引入了一个新的参数replica-ignore-maxmemory,其官方文档定义如下:
Maxmemory on replicas
By default, a replica will ignore maxmemory (unless it is promoted to master after a failover or manually). It means that the eviction of keys will be handled by the master, sending the DEL commands to the replica as keys evict in the master side.
This behavior ensures that masters and replicas stay consistent, which is usually what you want. However, if your replica is writable, or you want the replica to have a different memory setting, and you are sure all the writes performed to the replica are idempotent, then you may change this default (but be sure to understand what you are doing).
Note that since the replica by default does not evict, it may end up using more memory than what is set via maxmemory (since there are certain buffers that may be larger on the replica, or data structures may sometimes take more memory and so forth). Make sure you monitor your replicas, and make sure they have enough memory to never hit a real out-of-memory condition before the master hits the configured maxmemory setting.
To change this behavior, you can allow a replica to not ignore the maxmemory. The configuration directives to use is:
replica-ignore-maxmemory no

大意是redis作为slave时默认会无视maxmemory参数,这样可以保证主从的数据始终保持一致。当master/slave实际数据大小均小于其maxmemory设置时,这个参数没有任何影响,而这次丢失数据的原因正是因为主机B重启后作为slave时maxmemory(3GB)小于实际数据大小(6GB+),此时replica-ignore-maxmemory 默认开启保证作为slave时直接无视maxmemory的限制,而当执行sentinel failover mastername将主机B切换为新master后,新master不会受replica-ignore-maxmemory影响,发现自身maxmemory<实际数据大小后直接开始主动淘汰key,从而导致了数据丢失。
4. 至于主机B作为master执行淘汰key策略并最终进入只读状态后,其实际数据大小依然>3GB的原因,则是由于线上redis配置的策略是volatile-lru策略,该策略只会淘汰有过期时间的key,对于不过期的key是不淘汰的。

总结

总的来看这次故障的根本原因还是个人对于redis的配置、操作经验不足,如果在调整运行时maxmemory时能做到以下二者之一,这次故障就不会出现了:

  1. 调整运行时maxmemory时同时调整配置文件maxmemory保持一致--感谢@MSSQL123 指导点出CONFIG REWRITE 这个命令,在使用CONFIG SET maxmemory 修改后其实只需执行一次CONFIG REWRITE命令即可将最新运行时配置同步到静态的配置文件中,而不需要手动去修改配置文件同步了
  2. 将配置文件maxmemory设置为0--表示不限制内存使用。

正是因为对redis的认识和经验不足,没有想过到运行时配置与静态配置不一致可能导致的问题,这次不可避免的踩坑了。
但是,作为一个本职RD,半路接手基本靠自学的兼职运维,要考虑到maxmemory的运行配置与静态配置一致性问题好像也确实不是那么的理所当然🤔。
处理完这次故障后,特意在网上搜索了一番redis主从切换的注意事项、踩坑文章,想看看有没有人提到类似的坑,但是并无所获,难道这个坑真的没其他人踩(分享)过?陷入思考...
如果有经验丰富的小伙伴看到这里,也欢迎不吝赐教指导一下redis主从的切换的各类常识与常见大坑!

 

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

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

相关文章

Spring Boot 如何实现邮件发送

Spring Boot邮件发送 在现代的Web应用程序中&#xff0c;邮件通知已经成为了一项非常重要的功能。例如&#xff0c;在用户注册、密码重置、订单确认等方面&#xff0c;我们通常都会使用邮件来通知用户。在Spring Boot应用程序中&#xff0c;我们可以使用JavaMailSender来实现邮…

2022年长三角高校数学建模竞赛A题学在长三角解题全过程文档及程序

2022年长三角高校数学建模竞赛 A题 学在长三角 原题再现&#xff1a; 长三角高等教育规模和优质高等教育资源数量处于全国领先水平。从 2019年和 2013-2019 年的平均值来看&#xff0c;长三角地区人口数量在全国占比分别是 16.22&#xff05;和 16.10&#xff05;&#xff0c…

在Css上吃过的亏

一、前言 最近参加了公司的一个小程序的开发项目&#xff0c;虽然很简单&#xff0c;但是非常急三天就要交。本来就是实习生加上前端不熟练的我&#xff0c;最终在Css定位上吃了很大的亏。今天就来了解一下Css中的几个定位。 二、什么是定位 在Css中有一个position属性&…

技术干货 | ​Navicat 面向 PostgreSQL 查询超时的工具解决方案

早前&#xff0c;我们发表过一篇《PostgreSQL 与 Navicat &#xff1a;数据库的中坚力量》 &#xff0c;从产品的发展介绍了两者的渊源与共性&#xff0c;获得了许多童鞋的认可。而随着PostgreSQL 在国内热度愈发高涨&#xff0c;应用也愈发广泛。近期&#xff0c;我们收到许多…

Chirpstack服务器简介和搭建教程

LoRaWAN网络主要优势体现在低成本、广域连接和低功耗&#xff0c;同时具有较多的开源平台可供使用。使用Chirpstack服务器可以快速搭建本地LoRaWAN网络。本文重点介绍一下Chirpstack服务器是做什么的和Chirpstack服务器的安装教程&#xff1a; Chirpstack是一款多组件的、部署…

vue中 antdesginVue <a-image/>图片标签去掉蒙层(鼠标滑过)里面的“预览”二字 或者使用deep自定义样式不生效问题。

vue中 antdesginVue 图片标签去掉蒙层&#xff08;鼠标滑过&#xff09;里面的“预览”二字 或者使用deep自定义样式不生效问题。 看似去掉这两个字很简单&#xff0c; 其实搞了我一上午&#xff0c;是真的不好去掉呀&#xff0c;这里得吐槽下ant官方 。。。。什么deep呀都是不…

是面试官放水,还是公司实在是太缺人?这都没挂,字节跳动原来这么容易进...

字节是大企业&#xff0c;是不是很难进去啊&#xff1f;” “在字节跳动做软件测试&#xff0c;能得到很好的发展吗&#xff1f; 一进去就有12K&#xff0c;其实也没有想的那么难” 直到现在&#xff0c;心情都还是无比激动&#xff01; 本人211非科班&#xff0c;之前在华为和…

PostgreSQL 16 beta 重磅发布,OpenPie 再次引领中国贡献关键力量

PostgreSQL 一直被誉为全球最先进的开源关系数据库之一&#xff0c;在 DB-engines 排行榜上长期稳居前五。5 月 25 日&#xff0c;PostgreSQL 全球开发团队官方宣布&#xff0c;PostgreSQL 16 Beta 1 版本正式发布。 本次 PostgreSQL 新版本功能亮点众多&#xff0c;涉及多个模…

Docker环境java程序的时间设置

先上解决方案 java程序生成的时间、日志时间不对的解决方案&#xff1a; #在Dockerfile文件中加入以下两行代码&#xff0c;用于指定bild的镜像为东八区 ENV TZAsia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezoneDoc…

生产检验配置和操作

1、概念 在SAP系统的生产过程中运行中间产品或成品的质量流程&#xff0c;例如每个班次的检查等&#xff0c;在生产订单发布时生成检验批&#xff0c;在系统中进行检验的检验类型为03&#xff0c;当有生产订单发布时&#xff0c;将在系统中自动创建检验批。 2、前台和后台配置…

【操作系统】03.内存管理

存储器的层级结构 程序的运行 现代操作系统使用的连接方式&#xff1a;运行时动态链接 对某些模块的链接推迟到程序执行时才进行 现代操作系统使用的装入方式&#xff1a;动态重定位 程序装入内存后&#xff0c;逻辑地址不会立即转换成物理地址&#xff0c;而是推迟到指令执行…

Energy-Based Learning for Scene Graph Generation

[2103.02221] Energy-Based Learning for Scene Graph Generation (arxiv.org) 目录 Abstarct 1 Introduction 2 Approach 2.1 Scene Graph Generation 2.2 Energy Based Modeling 2.3 Energy Models for Scene Graphs Generation 2.4 Energy Model Architectue 2.4.1…

PCB多层板为什么都是偶数层?奇数层不行吗?

PCB板有单面、双面和多层的&#xff0c;其中多层板的层数不限&#xff0c;目前已经有超过100层的PCB&#xff0c;而常见的多层PCB是四层和六层板。那为何大家会有“PCB多层板为什么都是偶数层&#xff1f;”这种疑问呢&#xff1f;相对来说&#xff0c;偶数层的PCB确实要多于奇…

朋友面试字节要求月薪25K,明显感觉他背了很多面试题...

最近有朋友去字节面试&#xff0c;面试前后进行了20天左右&#xff0c;包含4轮电话面试、1轮笔试、1轮主管视频面试、1轮hr视频面试。 据他所说&#xff0c;80%的人都会栽在第一轮面试&#xff0c;要不是他面试前做足准备&#xff0c;估计都坚持不完后面几轮面试。 其实&#…

Unity WebGL打包配置本地服务器

第一步打包 1&#xff09;、先对Player Setting进行设置 2&#xff09;、设置打包的窗口大小 3&#xff09;、遇到异常以及压缩格式 第一个启用异常&#xff0c;指用户指定在运行时意外的代码行为&#xff08;通常被认为错误&#xff09;如何被处理&#xff0c;有三个选项…

进程(四)

进程四 2.21 管程2.22 死锁的概念2.23 死锁的处理策略2.23.1 破坏四个条件2.23.2 动态策略: 避免死锁2.23.3 死锁的检测和解除 2.21 管程 本小计知识概览 为什么要引入管程 管程的定义和基本特征 管程是一种特殊的软件模块&#xff0c;有这些部分组成: 局部于管程的共享数据结…

javaWeb ssh微博系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh微博系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开 发。开发环境为TOMCAT7.0,Myecli…

智慧校园建设主要包括哪些方面的内容?

在当今数字化的时代&#xff0c;越来越多的学校开始实施智慧校园计划&#xff0c;旨在为学生和教师提供更加高效、便捷的学习和教学环境。 那么&#xff0c;究竟什么是智慧校园呢&#xff1f;智慧校园建设主要包括哪些方面的内容&#xff1f;这篇就来详细讲一讲&#xff01; …

3年外包出来,华为、字节全都一面挂,我哭死.....

测试员可以先在外包积累经验&#xff0c;以后去大厂就很容易&#xff0c;基本不会被卡&#xff0c;事实果真如此吗&#xff1f;但是在我身上却是给了我很大一巴掌... 所谓今年今天履历只是不卡简历而已&#xff0c;如果面试答得稀烂&#xff0c;人家根本不会要你。况且要不是大…

字节软测划水四年,内容过于真实......

先简单交代一下吧&#xff0c;潇潇是某不知名211的本硕&#xff0c;18年毕业加入一个小厂&#xff0c;之后跳槽到了字节跳动&#xff0c;一直从事测试开发相关的工作。之前没有实习经历&#xff0c;算是四年半的工作经验吧。 这四年半之间他完成了一次晋升&#xff0c;换了一家…