线上缓存不一致问题排查

缓存不一致问题

背景

会员相关有:

  • 综合系统 :会员的基础CRUD ,旧系统,慢慢废弃,不再维护。
  • 会员系统 :从综合系统里拆分出来的,有基础服务,接口服务,数据同步服务,SSO服务等。 每个服务都是单独的应用。

两个系统共用同一张表,只是维护的字段不一样。

email【邮箱】是我们新版本中新支持的功能。综合系统没有 email 字段,会员系统里有 email 字段。

第一次反馈

用户反馈说: 邮箱收不邮件,去设置中看,邮箱设置会自动消失。重新设置一下就好了。

定位问题

一) 排查数据问题

怀疑是综合系统中,将 email 字段更新成了默认的空值 。

系统缺少必要的日志,无法追踪问题。并且缺少sql日志. 无法定位具体问题。

观察了系统监控,没有异常。 内存,网络也没有波动。问题抛给了测试同学,希望能复现出来。

第二次反馈

用户反馈说:又出现邮箱收不到邮件,还没来得及重置,但过了大概一个小时,自动好了。

定位问题

一)排查数据库

此时用户没有做更新操作。保护了数据库现场。

马上查询数据库. 得到以下结果:

  1. 用户的 email 是存在的。
  2. 数据的最后更新时间,还是用户上次反馈的时间。

数据现场表明 , 自从上次用户更新过后,没再发生过变化 。字段丢失,然后自动恢复显然不是发生在数据库上。

此时想到是多服务间的数据不一致性。

二)排查缓存

此时想到是缓存问题。

经过代码求证。 综合系统和会员系统是用的两个缓存key,所以不存在新旧系统的缓存冲突问题。

二) 排查服务

此时又想到是不同服务间的字段不一致,导致缓存不一致的可能性。

由于每个服务都是单独的应用。对于 email 字段,只有基础服务,接口服务使用到了。 上线时只升级了这两个服务,其他服务没有做相应升级。

也就是说,其他服务在做查询时,是没有 email 字段的 , 那么在写缓存时也是没有的。

到这一步,基本确定是不同服务间的缓存更新,导致的缓存不一致问题。基本符合用户描述的问题。

于是将步骤同步给测试同学,由测试同学去复现 。

问题症结

尴了尬的。 居然没有复现出来。

这时才注意到另一个点。 缓存默认时长是 6 小时 。 用户有说过大概一个小时后恢复了。

用户是持续性事件 ,缓存周期是 6 小时 , 不可能只一个小时就更新了缓存。

辅助工具不给力

一)运维平台的 缓存查询功能 , 由于年久失修, 并且过度设计,已经不能支持会员系统的缓存查询 。

二)线上的缓存服务器只开放给运维人员 , 开发负责人都没权限 的。 关键运维还没人值班,大晚上也找不到人 。

第三次反馈

用户反馈说:邮件又不生效了, 此时设置界面也没有邮箱了 。 给我些时间定位问题,他先不重置。

大晚上的 。 正在找不到问题点时 , 用户竟然还在线 , 并且还在关注问题 。 (中国好用户)

马上去查询数据库 ,得到以下结果:

  1. 用户的 email 字段还是存在的
  2. 数据的最后更新时间,还是用户第一次反馈的时间。

由此可以确定 。MD,就是缓存的问题 。

至此的定位结果

  1. 确认是缓存不一致问题 。
  2. 理论上应该是服务间数据不一致导致的缓存不一致。
    1. 无法复现
    2. 无法解释一小时自动恢复

缺少必要的支持,问题只能先暂停一下。 跟用户沟通好后 , 决定明天如果还找不到根源,就先把会员系统的其他所有服务都升级一把。

缓存平台,由于运维人员维护不力 ,必须得催促一下。 太影响工作了。

后记

也就是第二天了 。

先找运维要来了缓存服务器权限 , 由于没有现场, 想来问题肯定不止影响一个用户。去数据库里找了几个活跃用户, 果然试也没几个就找到了问题的用户。

找到了问题缓存 。 是由于数据同步服务,在查询数据时,写缓存导致把原缓存覆盖了。

理论上会员基本的CRUD都应该由基础服务来提供接口操作 , 但由于开发人员的不规范开发 , 在数据同步服务直接操作了数据库和缓存 。

问题解决

升级了数据同步服务, 问题就解决了。

但没有完美解决 , 后续很大概率还会出现服务升级不同步, 及开发不规范导致的缓存不一致问题。 需求从技术层面解决服务间缓存不一致的问题。

解决缓存不一致

解决思路:

  1. 对缓存添加版本号
  2. 版本号是在打包时生成 ,减少人工成本。
  3. 当 缓存版本 》= 当前服务版本,ok,没问题,缓存是最新的
  4. 当 缓存版本 《 当前服务版本 , 有问题。缓存旧,不适合当前服务使用。 那么淘汰缓存 ,重新生成。

好了, 有活干了, 对缓存的封装,要赶快做起来了。

最后

神奇的一小时 ,还是没解出来 。 还有 MD,测试没复现是 测试的同学步骤错了。。。

原文地址:https://www.cnblogs.com/ElEGenT/p/12578512.html

时间: 2024-07-29 05:13:12

线上缓存不一致问题排查的相关文章

线上FullGC频繁的排查

线上FullGC频繁的排查 问题 前段时间发现线上的一个dubbo服务Full GC比较频繁,大约每两天就会执行一次Full GC. Full GC的原因 我们知道Full GC的触发条件大致情况有以下几种情况: 程序执行了System.gc() //建议jvm执行fullgc,并不一定会执行 执行了jmap -histo:live pid命令 //这个会立即触发fullgc 在执行minor gc的时候进行的一系列检查 执行Minor GC的时候,JVM会检查老年代中最大连续可用空间是否大于了

关于GC(上):Apache的POI组件导致线上频繁FullGC问题排查及处理全过程

某线上应用在进行查询结果导出Excel时,大概率出现持续的FullGC.解决这个问题时,记录了一下整个的流程,也可以作为一般性的FullGC问题排查指导. 1. 生成dump文件 为了定位FullGC的原因,首先需要获取heap dump文件,看下发生FullGC时堆内存的分配情况,定位可能出现问题的地方. 1. 1 通过JVM参数自动生成 可以在JVM参数中设置-XX:+ HeapDumpBeforeFullGC参数. 建议动态增加这个参数,直接在线上镜像中增加一方面是要重新打包发布,另一方面

线上性能问题初步排查方法

文章出处http://ifeve.com/find-bug-online/ 有时候有很多问题只有在线上或者预发环境才能发现,而线上又不能Debug,所以线上问题定位就只能看日志,系统状态和Dump线程,本文只是简单的介绍一些常用的工具,帮助定位线上问题. 问题定位 1: 首先使用TOP命令查看每个进程的情况,显示如下: top - 22:27:25 up 463 days, 12:46, 1 user, load average: 11.80, 12.19, 11.79 Tasks: 113 t

一次线上多线程程序问题排查

问题描述: 周一发现线上的一个程序从上周日一直运行"卡住"了十多个小时,本来是10MIN一次更新数据的,导致现在数据一直停留在过去,并且由于程序一直"卡住"不报错,使得我们收不到报警短信通知. 问题分析与定位: 根据报错日志来看,是一个类A的static区域发生了异常,由于在static区域并没有catch住这个异常,导致类A无法加载成功,JAVA异常打印如下: java.lang.NoClassDefFoundError: Could not initialize

线上问题排查

线上操作与线上问题排查实战 技术同学需要经常登录线上的服务器进行操作,58到家架构部/运维部/58速运技术部,联合进行了一次线上操作与线上问题排查实战演练,同学们反馈有收获,特将实战演练的问题和答案公布出来,希望对大家也有帮助. 一.了解机器连接数情况 问题:1.2.3.4的sshd的监听端口是22,如何统计1.2.3.4的sshd服务各种连接状态(TIME_WAIT/ CLOSE_WAIT/ ESTABLISHED)的连接数. 参考答案: netstat -n | grep 1.2.3.4:2

线上服务CPU100%问题快速定位实战--转

来自微信公众号 架构师之路 功能问题,通过日志,单步调试相对比较好定位. 性能问题,例如线上服务器CPU100%,如何找到相关服务,如何定位问题代码,更考验技术人的功底. 58到家架构部,运维部,58速运技术部联合进行了一次线上服务CPU问题排查实战演练,同学们反馈有收获,特将实战演练的试题和答案公布出来,希望对大家也有帮助. 题目 某服务器上部署了若干tomcat实例,即若干垂直切分的Java站点服务,以及若干Java微服务,突然收到运维的CPU异常告警. 问:如何定位是哪个服务进程导致CPU

蚂蚁金服技术专家分享25个分布式缓存实践与线上案例

前言: 本文主要介绍使用分布式缓存的优秀实践和线上案例.这些案例是笔者在多家互联网公司里积累并形成的优秀实践,能够帮助大家在生产实践中避免很多不必要的生产事故. 一.缓存设计的核心要素 我们在应用中决定使用缓存时,通常需要进行详细的设计,因为设计缓存架构看似简单,实则不然,里面蕴含了很多深奥的原理,如果使用不当,则会造成很多生产事故甚至是服务雪崩之类的严重问题. 1.容量规划 缓存内容的大小缓存内容的数量淘汰策略缓存的数据结构每秒的读峰值每秒的写峰值2.性能优化 线程模型预热方法缓存分片冷热数据

轻松排查线上Node内存泄漏问题

I. 三种比较典型的内存泄漏 一. 闭包引用导致的泄漏 这段代码已经在很多讲解内存泄漏的地方引用了,非常经典,所以拿出来作为第一个例子,以下是泄漏代码: 'use strict'; const express = require('express'); const app = express(); //以下是产生泄漏的代码 let theThing = null; let replaceThing = function () { let leak = theThing; let unused =

一个Flume线上问题的排查

最近在做一个分布式调用链跟踪系统, 在两个地方采用了flume ,一个是宿主系统 ,用flume agent进行日志搜集. 一个是从kafka拉日志分析后写入hbase. 后面这个flume(从kafka拉日志分析后写入flume)用了3台  , 系统上线以后 ,线上抛了一个这样的异常: Caused by: org.apache.flume.ChannelException: Put queue for MemoryTransaction of capacity 100 full, consi