删除缓存引发的服务停止事故

2022-08-14 18:29:38阅读 15评论 1

起因

对接的一个应用,数据同步到身份系统,由于数据中没有的唯一属性值,身份系统将数据中的人员当作注销进行处理,导致这些同步过来的人员无法通过单点登录系统进行登录。

恢复数据

现场人员将数据库还原到前一天的状态后,人员可进行登录,但登录后,没有应用的权限。经过分析,发现人员没有权限的原因是由于数据库和redis的数据不一致导致(数据库中人员有权限,redis中人员没有权限,请求从redis中获取到权限)。

清除缓存

一般来说,数据库和redis中数据不一致,清除reedis缓存后,系统会自动重新将数据库的数据缓存到redis。当时就采用清除redis缓存,让系统自动重新缓存的这种方案。

但从清除redis缓存后,发现权限系统中报出大量有关数据库的错误,权限系统也无法提供服务,最后导致整个系统瘫痪。

现场人员多次尝试重启权限系统,但权限系统运行后,出现大量报错,并无法对外提供服务。

恢复redis缓存

通过运行一个脚本,读取数据库,再将数据库中的数据读取出来后推送到rredis,以这种方式恢复redis缓存。

经过几个小时后,数据库中某一张权限表数据终于恢复到redis中,但权限系统仍然启动后出现同样的报错且无法提供服务。

我们正在思考为啥恢复redis中缓存数据后,还无法恢复正常,突然实施人员说系统已经跑起来了,而且可用提供无法,经测试确实可用使用,然后我们通知客户系统恢复,我们也下班了。

再次瘫痪

第二天,实施人员又反馈说系统又挂了,无法启动。我去到现场,重启系统,发现仍然报数据库异常,和昨天一样。

把日志取出来,从日志中看到有几个ip地址重复向权限系统发出请求,调用用户权限。经过对该接口代码的查看,发现这个接口会先从redis中获取权限信息,如果redis中没有再去数据库查询权限信息。从日志中可看出,请求是绕过redis直接达到数据库的。

监控数据库线程show processlist,可以发现系统在启动后,出现大量的线程在查询一张表。然后发现这又是一张权限表,而昨天缓存到redis的是另一张表的数据。经沟通了解到,有两张权限表,昨天我们缓存到redis的是一张已经废弃的权限表,这张才是现在使用的权限表。

重新恢复

为了不影响业务,我们先将频繁发送权限请求的应用的ip地址移除出白名单,启动权限系统,经测试能稳定提供无法,并且日志中未出现异常。

然后我们将这张新的权限表的数据缓存到redis,重启权限系统,放开白名单,然后观察数据库线程情况,没有几乎发现有查询数据的线程,也就是说redis中的缓存生效了,经过很长时间观察,再没有出现权限系统无法提供服务的情况。

总结

不可以直接将redis中缓存清掉,当请求量足够大时,请求直接打到数据库,很有可能把数据库弄瘫痪掉,导致系统无法对外提供服务,从而影响到业务。

系统出现redis缓存和数据库数据不一致的情况,正确的处理是,通过脚本遍历数据库读取最新数据,一个个替换redis中的数据。

访客03-09 10:56

亲历,哈哈