造成的一次线上事故

发布于 2025-01-04  28 次阅读


周四晚上上线了一个需求,周五早上产品来测的时候给我发消息,说有报错问我怎么回事。同时我又被拉进了一个告警群,当时并没有觉得这个告警和我有关系,因为类似的告警拉群实在太多了。然后我就按照产品给的查询条件去测试了一下,发现有些能查出来,有些就是报错。于是我又去看日志,发现查询ES有NPE,然后发现返回的异常有服务不可用。我想这线上为啥还会服务不可用,只有我在线下调试的时候占用了端口才会这样(现在还没意识到是线上机器崩了)。

然后这时我mentor和我说你昨天和XX一起发布的?你有没有发父pom?这是我有点慌,我心想不会这告警是我搞得吧。然后发现机器出现了fgc,直接崩了,下游服务有调用失败的,这时候先扩容了2台机器,然后开始排查问题。一开始是觉得数仓查询到的数据量太大了,把内存给占满了。但是根据查询的日志,数仓查询出的数据都是1条1条的,既然数仓这边没问题,那应该就是查询ES的时候出现的问题了。

于是定位到查询ES代码,发现是会根据条件把所有符合的数据查询出来,查询条件有可能按日,按周,按月,线上数据一天的大小就有1个g,机器的大小只有8g,然后产品一开始是按周查询的,第一下也许能查出来,但已经濒临内存爆满了,再次查询只会触发fgc了。

但依据产品的需求,当前日志只能把相关数据全部查出来,然后去重排序,但是线上数据量太大了支持不了这个操作。

所以新的优化方案是新建一个索引,只存储需要的字段,然后添加一个需要排序的计数字段,先在es中排完序后再分页查询。新增or更新思路就是,根据id查询是否存在这条数据,如果不存在则直接添加,如果存在的话再判断此id下的visitid是否与要添加的相同,如果相同则count+1,不同则直接添加。为了防止更新冲突,需要使用redis加锁进行控制。

总其原因就是因为自己经验还是太少,这种情况确实线下是测试不出来的,线下的数据量太少。自己没意思到线上的数据量会导致机器崩掉,这次也算是学习了些经验了。

人生の意味は平凡ですか、それとも素晴らしいですか?
最后更新于 2025-01-04