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

news2025/1/10 4:04:23

背景

最近一组业务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,从而导致了数据丢失。 3. 至于主机B作为master执行淘汰key策略并最终进入只读状态后,其实际数据大小依然>3GB的原因,则是由于线上redis配置的策略是volatile-lru策略,该策略只会淘汰有过期时间的key,对于不过期的key是不淘汰的。

总结

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

  1. 调整运行时maxmemory时同时调整配置文件maxmemory保持一致。

  2. 将配置文件maxmemory设置为0--表示不限制内存使用。

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

最后

如果有经验丰富的小伙伴看到这里,也欢迎不吝赐教指导一下redis主从的切换的各类常识与常见大坑!

原文:http://www.cnblogs.com/AcAc-t/p/redis_master_switch_failure.html

如果感觉本文对你有帮助,点赞关注支持一下,想要了解更多Java后端,大数据,算法领域最新资讯可以关注我公众号【架构师老毕】私信666还可获取更多Java后端,大数据,算法PDF+大厂最新面试题整理+视频精讲

 

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

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

相关文章

从“0”到“1”!低代码开发和云计算的碰撞,引领数字化转型浪潮!

随着互联网技术的飞速发展&#xff0c;数字化转型已经成为企业转型升级的必经之路。而在数字化转型的过程中&#xff0c;云计算和低代码开发逐渐成为新技术的代表&#xff0c;为企业提供更高效、更灵活的技术支持&#xff0c;让企业赢得更大的竞争优势。 云计算的发展 云计算是…

三阶段项目

DHCP分配不到冲突地址 需要重启 再分配 用这个命令 reset ip pool name vlan40 all ospf&#xff1a; 建立邻居表&#xff1a;报文&#xff1a;hello报文 状态&#xff1a;down int 2-way 选举DR 同步数据库&#xff1a;报文&#xff1a;DD-LSR-LSU-LSACK 状态&#xff…

C语言-printf打印%*s、%.*s与%-.*s的区别

一、简介 在平时的使用中&#xff0c;会经常使用到printf进行打印&#xff0c;而最长使用的方式是printf("%s",string)进行打印。但是有个问题&#xff0c;如果string结尾不是0。那么printf会继续打印&#xff0c;直到遇到0为止。这样就会有内存溢出的风险。显然&…

(三)ArcGIS空间数据的转换与处理——栅格数据变换

ArcGIS空间数据的转换与处理——栅格数据变换 目录 ArcGIS空间数据的转换与处理——栅格数据变换 1.地理配准2.平移3.扭曲4.旋转5.翻转6.重设比例尺7.镜像 数据变换是指对数据进行诸如放大、缩小、翻转、移动、扭曲等几何位置、形状和方位的改变等操作。对于 栅格数据的相应操…

类和对象 - 练习题(C++)

目录 1、求123...n 题目链接&#xff1a; 题目&#xff1a; 题目描述&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 2 计算日期到天数转换 题目链接&#xff1a; 题目&#xff1a; 题目描述&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 3 日期差值 题目链接&…

人工智能学习07--pytorch18--目标检测:Faster RCNN源码解析(pytorch)

参考博客&#xff1a; https://blog.csdn.net/weixin_46676835/article/details/130175898 VOC2012 1、代码的使用 查看pytorch中的faster-rcnn源码&#xff1a; 在pytorch中导入&#xff1a; import torchvision.models.detection.faster_rcnn即可找到faster rcnn所实现的源…

NIFI分页获取Postgresql数据到Hbase中_实际操作---大数据之Nifi工作笔记0049

首先看一下整体流程,可以看到这里用的PutHbaseJson处理器,把数据导入到 hbase中的 注意这里也可以使用PutSql导入数据,通过phoenix的jdbc驱动,然后把数据利用PutSql处理器导入到 Hbase中,但是我这里的时候报错了,然后一直没解决,所以最后用了PutHbaseJson处理器,把数据存入到…

【LinuxShell】linux防火墙之SNAT策略和DNAT策略

文章目录 前言一、SANT策略1.SNAT策略概述2.SNAT的典型应用环境3.SNAT的工作原理4.SNAT策略的应用SNAT转换前提条件SNAT策略打开方式SNAT实验过程 5.知识扩展 二、DNAT策略1.DNAT策略概述2.DNAT的典型应用环境3.DNAT的工作原理4.DNAT策略的应用DNAT转换前提条件DNAT地址转换方式…

linux管道通信原理

管道&#xff0c;通常指无名管道&#xff0c;是 UNIX 系统IPC&#xff08;InterProcess Communication)最古老的形式。 1、特点: 1.它是半双工的(即数据只能在一个方向上流动) &#xff0c;具有固定的读端和写端 2.它只能用于具有亲缘关系的进程之间的通信(也是子进程或者兄弟进…

python 读写 json,csv,txt,docx,xlsx,xls文件大全

目录 前言一、读写json1.1 读1.2 写1.2.1 list类型写入1.2.2 dict类型写入 二、读写csv2.1 读2.2 写2.2.1 list类型写入2.2.2 dict类型写入 三、读写txt3.1 读3.2 写按行写入&#xff08;手动添加换行符\n&#xff09;按行写入&#xff08;python添加换行符\n&#xff09;3.2.1…

Linux:Firewalld防火墙

Linux&#xff1a;Firewalld防火墙 一、Firewanlld防火墙概述二、Firewalld和Iptables的关系三、Firewalld网络区域3.1 Firewalld 区域的概念&#xff1a;3.2 firewalld防火墙预定义了9个区域3.3 firewalld数据处理流程 四、Firewalld防火墙的配置方法五、Firewalld-config图形…

RHCSA 8考题超级详细解析(2022最新版)本人已过

文章目录 1.配置IP地址2、配置软件仓库3、调试SELinux4、创建用户账户5. 配置cron计划任务6、创建共享目录7、配置NTP时间客户端8. auto自动挂载9、配置文件权限10、配置用户账户11、查找文件12、查找字符串13、 创建归档14、配置sudo提权15、设置密码默认策略16、配置umask值1…

海格里斯HEGERLS库架合一|仓储托盘四向穿梭车在冷库冷链行业中的应用

当前的物流行业正在从劳动密集型向技术密集型转变&#xff0c;物流系统越来越明显的向呈现出自动化、数字化、柔性化、智能化的发展趋势。以堆垛机为代表的自动化仓储系统&#xff0c;取货对场地要求比较高&#xff0c;多建在12M以上的新仓库。而对于不规则的、层高较低的老仓库…

【python资料】热图和Matplotlib.imshow()函数

一、说明 Matplotlib是一个强大的Python数据可视化库&#xff0c;可以绘制各种类型的图形&#xff0c;其中包括热图。热图通常用于表现数据的分布和趋势。本文用一个简单的例子&#xff0c;告诉大家用Matplotlib绘制热图的基本操作语句。 二、热图的概念 2.1 基本概念 热图&am…

7EBG-10-C-B-107EBG-20-B-B-10比例先导溢流阀放大板

7EBG-10-B-B-10、7EBG-20-C-B-10、7EBG-30-H-B-10、7EBG-10-C-B-10、7EBG-20-B-B-10、7EBG-30-C-B-10特性&#xff1a; ● 该阀是由高性能型比例先导式溢流阀和低噪音型溢流阀组合而成&#xff0c;进行压力与输入电流成比例的压力控制&#xff0c;能够达到无段式控制特性。 ●…

c++(内存管理)

本节目标&#xff1a; 1、c/c内存分布 2、c语言中动态内存管理方式 3、c中动态内存管理 4、operator new 与 operator delete函数 5、new和delete的实现原理 6、定位new表达式&#xff08;placement - new&#xff09; 7、常见面试题 目录 1.c/c内存分布 2、c语言中动…

StringRedisTemplate和RedisTemplate的区别

StringRedisTemplate和RedisTemplate的区别 springboot提供了两种redis访问工具类StringRedisTemplate和RedisTemplate&#xff0c;为什么spring官方会提供两种不同redis访问工具呢&#xff1f;两者主要的的区别在于redis的key和value的序列化方式不同&#xff0c;并且StringR…

手把手教你制作AI孙燕姿,让你的抖音视频火遍全网!

最近“AI孙燕姿”翻唱”的《发如雪》《爱在西元前》等歌曲在B站、抖音、快手等短视频平台爆火&#xff0c;截止到发稿前抖音的播放量已经超1700万。 目前AI孙燕姿制作教程资料较少&#xff0c;网上搜到几个都是使用开源项目Sovits来训练模型&#xff0c;使用门槛较高。 本文以…

云时通 X 九毛九 | SRM系统助力连锁餐饮行业高效管理供应链

餐饮行业作为第三产业中的传统服务性行业之一&#xff0c;始终保持旺盛的发展势头&#xff0c;随着时代的进步&#xff0c;现代餐饮企业更多以连锁业态发展&#xff0c;其特点是多种形式相结合而生&#xff0c;将新颖的就餐空间与潮流文化和传统的经典美味互相融合&#xff0c;…