大促宕机的思考
2025-01-22 08:19:30    894 字   
This post is also available in English and alternative languages.

复盘大促宕机生产事故,重新审视新接手的项目。


1. 背景

A部门大部分顾问离厂,自有员工接手系统,被抽掉入A部门某组;

核心系统主要技术栈:Nginx(负载) + Lua(参数处理/请求分发) + JBoss(业务处理) + Redis(缓存) + Solr(底层存储)


818公司大促活动,18号凌晨系统QPS达到峰值22000,底层Solr集群被打挂,上层应用系统崩溃。

紧急重启Slor集群、应用系统;应用系统间歇性宕机,先后重启了三次才恢复。


2. 应用系统启动失败

重启应用时,值班人员没有切断前端访问流量;

这边应用在重启,那边大流量不停的访问,导致应用解压缩war包失败,出现大量异常,最终超过文件句柄连接数,导致重启失败。

最后一次重启成功,是按照标准流程来的,断开流量、重启应用、启动成功后,再接入流量。


3. 复盘分析

3.1. 业务

818之前三个版本的需求,业务扩张非常庞大,主站内各个页面、活动页,增加了四十几个调用方。

虽然818之前经历了618大促,但是由于618时,外部接口调用没有全部放开,所以618的QPS只有6000左右,直接导致了818后面预估容量出现较大误差。


3.2. 预估/压测/评审

业务扩张之后,系统没有一个全面准确的流量评估,流量应该结合 上游调用系统、业务/运营、产品 三方结果 综合评估,并包含一定的流量放大(冗余量)。

大促前的压测不重视、不全面、不准确。


3.3. 技术层面

3.3.1. solr

solr集群脆弱,最大承受3000TPS,818峰值6000,导致solr崩溃;后台程序,在高峰时刻(八点、十二点)有定时任务,向solr集群写数据,消耗、占用很大一部分资源。


3.3.2. 缓存

3.3.2.1. 缓存问题

在最后一个发布版本中,错误更改了一部分的本地缓存策略,导致部分场景本地缓存失效。

(当时评估不会对业务有大影响,忽视了对性能影响,而且错过了发布周期,所以带着该问题继续运行)

程序中做了二级缓存,一级是本地缓存、二级是redis缓存;缓存的数据内容是从solr查出来的原数据,没有做去重等业务处理。


3.3.2.2. 缓存穿透

很多业务场景都与会员相关,当时只顾着对这部分业务加Redis缓存;遗漏了其他的业务场景。

在零点峰值时,很多流量打到了solr集群的原因,是有很多新用户,没有做缓存。


3.3.3. 日志

临时接手该应用短,期间一直在进行业务需求开发,没有时间梳理代码。

后期监控发现,老代码中有很多日志信息,大量日志信息输出影响IO性能。


4. 优化

  1. 重新评估系统抗压能力

  2. 对所有接口进行混压,压测要贴近生产。

  3. solr集群切换到Elasticsearch集群

  4. 后台定时任务逻辑优化

  5. 本地缓存策略全面排查

  6. 二级缓存的数据进行梳理优化

  7. 新用户做临时会员号/设备号,走缓存

  8. 梳理/删除 老代码中无用、耗费性能的代码

  9. 流控