一、背景
2015.7.31 10.36.14.*网段的TOR故障一小时,网络故障恢复后,redis nj多个从主从同步异常:

   除slave0外,其他slave的offset均比master大。注:redis的主从之间通过offset进行增量同步,即从向主发送它当前存储数据的offset,主将这个offset之后的增量数据同步给从,以保证主从数据一致。然而线上出现从的offset比主大,说明主从同步的逻辑存在问题。

二、问题影响
Redis主从同步分三种:
1.全量同步(主从首次连接或者增量同步失败)
——redis主dump出所有的数据发给从;
2.增量同步(主从连接瞬断)
——redis主将slave发送的offset之后的数据发给从;
3.长连接同步(正常情况)
——redis主从维护一个长连接,redis主将所有写请求发给从;
该问题只会影响redis主和从的增量同步即网络瞬断时会影响同步,影响分为两种:
1.发生问题后,进行增量同步时从的offset比主大:增量同步失败,进行全量同步,对redis从中的数据不影响;
2.发生问题后,进行增量同步时从的offset比主小(出现问题时从的offset比主大,但是随着主写入数据,offset可能会超过从):主从增量同步异常,从中的数据比主少。
三、Bug定位
异常原因
由问题背景可看出bug由从的replica_offset引起,分析代码中会修改从的offset的逻辑:
初始化:从的offset是在向主请求增量同步失败后由主返回:

  从接受到”+FULLRESYNC”响应后,更新offset:

  Offset更新:全量同步完成后,主从长连接正常同步时,每次请求offset均自增:

  结合offset初始化和更新的代码逻辑,可以推断offset异常由主从全量同步引起,原因如下:

1.如背景所述,发生问题时主从连接断开,无法进行正常同步,因此不存在正常同步导致offset异常;
2.正常同步中offset只会比主少,不会比主多。
源码分析
分析redis主处理增量同步的代码逻辑,画出简化的流程图如下:

抽出master返回offset逻辑如下:

Master会先设置psync_offset(要发给从的offset)为master当前的offset,然后判断是否有在做bgsave操作,如果已经有从在做bgsave,则复制已经在做bgsave的从的output buffer(这个buffer会作为dump同步完后的新增数据发送给从)——至此,问题已出现:

  当第一个从进行全量同步时,主将它当前的offset o1返回给从,并且开始做bgsave同时将新增的写请求数据写入第一个从的repl_buffer中,同步完dump数据后,从repl_buffer中发送增量数据,此时o1+增量数据刚好等于master的offset;

而在第一个从的bgsave未完成时,若第一个从申请全量同步,则主返回它当前的offset o2(必然比o1大),判断到slave1已在做bgsave,此时不再做bgsave,直接复制s1的repl_buffer到s2的repl_buffer中,并且master新增的数据也开始写到s2的repl_buffer中,同步完dump数据后,从repl_buffer发送增量数据并同步offset.
注意:
此时s1和s2的增量数据完全相同;
o2 > o1
o1 + 增量数据 = master的offset
因此从2的offset比主大。
四、问题修复
确定问题后,RD对代码进行了修复:需要做全量同步时,master不再返回当前的offset,而是返回首次做bgsave时保存的offset:

  缓存server.fullsync_repl_offset,每次全量同步时返回同样的offset。

五、测试
问题已修复,需要回归测试,测试做CR时仔细核对主从同步过程,发现有如下逻辑:

  若第一个从申请全量同步时,主已经在做bgsave(请注意,这里的bgsave是主自动触发的),这时会将从的offset标记为主当前的,并且标记从为WAIT_BGSAVE_START,等待bgsave结束后再次开启bgsave,而这时从的offset比主小。

六、新的问题
这种情况下,若主已在做bgsave:
从请求做全量同步,则主会返回从一个offset o1,并且标记从为WAIT_BGSAVE_START;
等bgsave结束后再次开启bgsave,记此时主的offset为o2,并将主的增量数据写到从的buffer中;
同步完dump的数据后同步增量数据,此时主的offset为o2+增量数据,而从的offset为o1+增量数据;
显然,o1<o2,这就造成同样的数据,从的offset比主小。

影响

事实上,这个问题若出现,将比上一个问题影响更大:
从的offset比主小,只要网络瞬断,则从的数据必然异常,并且会重复写一部分数据(o2-o1对应的数据段),造成线上主从数据不一致。
七、修复方案
可幸的是,在我们发现第二个问题后,redis官方给出了这一系列问题的解决方法:https://github.com/antirez/redis/commit/bea1259190a9f3c3850b074ef7d0af0bc3ea36a7
官方的解决方法为:
从申请做全量同步时,不再立即返回主的offset,而是放在buffer中作为增量数据发送。
八、总结
这个bug算是隐藏很深的一个超大bug了,在作者修复前,开源社区使用redis的公司应该都或多或少的受到了这个问题的影响。
目前来看,底层服务的这种bug很难发现:
功能测试实在无法覆盖层出不穷的异常场景,redis开源社区已有的自动化case数已达200多项,然而这个bug还是隐藏了很久;
QA和RD没有足够的精力去CR整个服务的代码。
测试应加大CR力度,对代码足够了解才能写出足够完善的case;
CR时应尽可能分析代码的所有逻辑,避免出现特殊情况;
问题定位:
测试中应注意的问题
CR建议
1.问题定位:
a) 分析bug产生的原因,尽可能详细到变量或者函数;
b) 阅读代码逻辑,查看变量/函数的初始化位置/调用位置或改变位置;
c) 分析变量/函数出错可能的原因,检查对应的代码逻辑;
2.测试:
对QA来说,CR不只是阅读代码逻辑,也要检查代码逻辑的问题——CR代码时尽量画出一个流程图(至少大脑里要有一个),之后分析代码逻辑:
a) 检查各个变量的初始化及调用位置,判断是否会有脏值;
b) 检查动态内存的申请和释放位置,判断是否会内存泄漏或者使用野指针;
c) 检查代码分支,不同的分支是否能做正确的响应;
————————————————
版权声明:本文为CSDN博主「百度MTC」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/baidu_mtc/article/details/50594988

Redis主从同步异常问题记录相关推荐

  1. 实战演练:MySQL手动注册binlog文件造成主从同步异常

    m 墨墨导读:本文是作者用MySQL数据库手动注册binlog文件造成主从同步异常后,详述整个分析与解决的过程. 云和恩墨大讲堂线上分享:<weblogic 优化> 时间:2019年7月3 ...

  2. redis 主从同步到分布式集群

    Redis 集群是一个提供在多个Redis节点间共享数据的程序集 通过集群的配置可以解决:机器故障.容量瓶颈.QPS瓶颈等 主从同步 redis主从结构有一主多从和级联结构 一主多从:master将数 ...

  3. Redis主从同步机制详解

    1.什么是高可用? 单机redis支撑的并发量有限(一般QPS在1W-几W不等),如果并发量大可能导致redis挂掉:redis配置不合理,fork子进程同步也可能导致redis挂掉(伪挂):操作系统 ...

  4. mysql主从skip1677_解决字符集不同引起的主从同步异常1677报错问题

    之前的一篇文章中,我们遇到了主从同步的一个问题,错误代码:1236,详细请看 今天,突然发现测试环境的主从同步关系断开了,报错代码:1677 一.问题错误信息 Last_SQL_Errno: 1677 ...

  5. 五、Redis主从同步

    Redis 主从同步 一.复制 二.旧版复制功能的实现 2.1.同步操作 2.2.命令传播操作 三.旧版复制功能的缺陷 四.新版复制功能的实现 五.部分重同步的实现 5.1.复制偏移量 5.2.复制积 ...

  6. Docker搭建Redis主从同步详细教程

    文章目录 介绍: redis主从同步概念 redis主从同步原理 redis主从同步流程图 搭建redis主从详细步骤: 拉取redis镜像 创建所需文件夹,用于映射容器相应文件路径 运行容器指定挂载 ...

  7. 【Redis】Redis主从同步中数据同步原理

    [Redis]Redis主从同步中数据同步原理 文章目录 [Redis]Redis主从同步中数据同步原理 1. 全量同步 1.1 判断是否第一次数据同步 2. 增量同步 3. 优化Redis主从集群 ...

  8. 六、redis主从同步

    参考Redis 的主从同步,及两种高可用方式 010.Redis 主从架构搭建及原理详解 一.介绍 1.简介 redis的主从就是多台redis的数据保持一致.redis主服务器可写入和读取,从服务器 ...

  9. Redis主从同步模式(replication)

    主从同步模式(replication) 主从同步是指以一个节点为基准节点,将数据同步给从节点,使得主从节点的数据保持一致,主节点一般也称为Master,从节点Slave,一个Master节点可以有多个 ...

最新文章

  1. 基于mysql传统复制模式转为GTID模式 mysql 5.7版本
  2. 视网膜脱落相关知识(持续更新中)
  3. 【笔记】一些linux实用函数技巧【原创】
  4. c# oracle datasource,C# 连接Oracle 数据库 示例源码下载
  5. 2018 10 23
  6. 2 追踪光线=》2.6 反射光线
  7. 在Python中最快的HTTP GET方法是什么?
  8. MATLAB中施密特正交化的实现
  9. CABAC基于上下文的自适应二进制熵编码
  10. 8数据提供什么掩膜产品_喜茶、茶百道、书亦、古茗8月外卖热销产品数据全解析...
  11. Linux操作命令分类详解 - 目录文件(二)
  12. 织梦DedeCms技术资料
  13. phpcms system.php,phpcms_v9.6.0_UTF8 PHPcms系统开源 很有用 - 下载 - 搜珍网
  14. 工程师软技能~聊聊价值,价值观和价值积累
  15. 批量ping指定端口,批量测试IP地址是否通
  16. web前端进阶<7>:3d图像翻转效果
  17. android pppd log,未记录的pppd退出代码
  18. 人为什么活着__稻盛和夫的哲学
  19. 用委托实现信用卡还款
  20. c++入门 有关《c++关键字》 《命名空间》《缺省参数》《函数重载》《引用》《内联函数》《outo关键字》

热门文章

  1. Android开发之国家列表分组排序显示
  2. HTML中引入在线图片
  3. 4个有影响力的绩效管理最佳实践
  4. gitlab 503错误的解决方案
  5. python菜单栏_NUKE PYTHON 自定义菜单栏UI
  6. python字典的遍历,items()和iteritems()用法
  7. pythonsocket数据对接_python中socket接受数据的三种方法
  8. iOS高仿国美、二次元应用、点赞喷射动画、电影筛选页等源码
  9. Python获取当前时间(time模块)
  10. Qt各个版本最新下载地址(2020/3/13更新)