又出问题了、任何地方都不能信任了

作者: | 更新日期:

谁都不可信。

本文首发于公众号:天空的代码世界,微信号:tiankonguse

一、背景

2020年06月10日,我的 union 服务又出问题了。

分析这次故障的原因时,发现很多环节都没有自动发现问题的能力。

所以便思考,系统内部的各个环节其实并不能完全信任的。

如果要信任,就需要进行交叉检查,使用数据来证明确实是值得信任的。

二、强刷缓存

在容器平台上发布的时候,也就是 Iaas 基础设施,几百台容器里突然有一个容器从内存中读到了测试环境配置。

结果是直接导致正式环境的缓存数据被污染了。

之前的文章《如何洗数据》和《数据脏了怎么办》介绍过,我的系统在 2018 年的时候已经支持了指定一个全局 时间,然后将这个时间之前的所有缓存强制刷新掉。

所以当我确认我的系统有问题后,就需要开始刷新缓存数据了。

这里唯一的问题是刷新频率设置多大。

我刚开始不敢调的太大,计划慢慢翻倍的方式调大。

后来看反馈问题的人越来越多,大概估算一下,出问题的集群热点特别集中,会马上把新数据缓存起来,应该也没问题。

于是我就把刷新频率设置的很大很大,一下就全好了。

处理另外一个集群的时候,就没这么幸运了。
另一个集群是个大杂烩,热点非常不集中,直接触发频率上限,用来好久才恢复。

三、不信任配置

后台服务一般分两种配置。

一种是服务相关的,一般通过文件的形式下发到服务。
一种是集群管理或者运营相关的,一般在 DB 中储存,动态下发到服务。

这里就分三种情况了。

1、文件或者 DB 配置下发失败,服务不启动就不会污染数据。

千万不要走默认配置,默认配置说起来很好听,即使下发失败也可以启动服务。
但随着版本迭代,文件配置或者 DB 配置可能已经更新无数个版本了,默认配置可能早就不可用了。

所以前几个月,我遇到了文件下发失败,走默认配置无法正常服务后,就在文件中加了一个 flag 标识,来检查是不是默认配置,是默认配置就不启动服务。

2、文件 和 DB 配置按预期下发,皆大欢喜。

3、因某种原因,文件 或 DB 配置下发错环境。

比如我们最近在接入 cpplint 检查代码。
由于刚开始历史的有大量的不规范代码,我们规划是每周修改一些,然后发布一次。
通过这种小步迭代的形式,慢慢的把旧代码全部改成符合规范。

不管什么系统,都可能存在问题

这次就遇到了容器平台的 BUG,不知什么原因,几百台容器里面,有一个容器正式环境竟然下发了测试配置。

所以这时候,我们就不能完全相信一个配置系统了。

考虑到一个配置系统出问题的概率非常小,那两个配置系统结合起来,可以理解为几乎不会出问题了。

那怎么结合了,DB 配置和文件配置都下发一个环境的标识,比如正式环境是 1, 测试环境是 0。

程序启动的时候先判断标识是否一致,一致了认为没问题,正常服务,不一致了,就不要对外服务了,按容器启动失败处理。

四、不信任数据

作为缓存系统,为了容灾与隔离,会搭建多个集群。

这时候缓存集群与底层储存,缓存集群间就存在一致性问题了。

以前的时候,我们的重点都集中在了数据变更时,各集群是否一致。

也就是底层 CMS 把数据写入 NOSQL 后,我们会通过机制刷新所有缓存集群的数据。

但是我们不信任这个通知机制,所以新增了一个旁路程序。
大概逻辑是接收更新通知,拉各集群与底层的数据,检查数据一致性。

对于变更数据一致性问题,不信任了可以通过变更列表去一一检查。

可以服务正常运行的时候,怎么检查集群间与底层是否一致的呢?

发现这里还真没有好的办法,只能抽样检查。

一种是获取比较热门的请求 key,通过旁路程序隔一会检查一下,判断是否有问题。
一种是命中缓存时,把少量请求按没命中处理,然后对比回源的数据与缓存的数据,短期内数据没变更,数据又不一致了,进行修复,并发出告警。

第一种是无侵入式的,但是热门 key 列表不好获得(出问题的可能不在池子里),轮训周期也是一个问题,拉去 key 的哪些资料也是一个问题。
第二种是侵入式的完全自动化的,所有数据人人平等,出问题的数据越多,被发现的概率越高。唯一的问题是抽样抽多少。

当然,最好是两种都给支持了,既照顾到热门数据的监控,又照顾到大盘整体的监控。

五、最后

经历了这次问题,发现系统设计的时候,不能信任任何地方。

也就是,正常情况下,各个环节都没问题是不用说的。
而任何一个环节出问题的时候,系统应该具备适当的健壮性。

这个健壮性的目标是将影响降为最小。
比如读到错误的配置,那宁愿不服务,也不能污染储存数据,即自动规避问题。
而对于其他的设计,则需要增加旁路系统来监控设计是否符合预期,即及时发现问题。

思考题:旁路系统出问题了怎么办呢?

《完》

-EOF-

本文公众号:天空的代码世界
个人微信号:tiankonguse
公众号ID:tiankonguse-code

本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。

关注公众号,接收最新消息

tiankonguse +
穿越