发现严重问题
那天半夜三点被手机警报震醒,后台库存显示负三万件!头皮直接麻了,鞋都穿反了跑去开电脑。查日志发现是零点大促的秒杀活动,库存直接穿底,用户付了钱没货发,客服电话快被打爆。
第一次瞎折腾
第一反应是锁库存呗。吭哧吭哧给数据库热点商品加行级锁,上线后更完蛋。每秒订单量从五千暴跌到两百,服务器CPU直接飙红。用户骂街弹窗“系统繁忙”的频率比我眨眼还快。
- 加锁测试结果:压测工具刚启动十秒,订单库连接池直接撑爆
- 监控数据:200台服务器集体告警,磁盘IO爆满99%
- 客服反馈:投诉量激增300%,骂人词汇量丰富到能出词典
拆解真实瓶颈
蹲机房盯着监控图看了一天,发现坑在数据库写竞争。每次扣库存都要锁整条记录,十万个人抢一件商品时,数据库快被拆散架了。想起来去年在Redis做过计数器实验,抓过笔记本就画流程图:
- 把库存数预加载到Redis集群里
- 用户下单先走Redis原子减1
- 减成功才放行到数据库
- 搞个定时任务把Redis和数据库对账
掉进缓存大坑
部署完美滋滋点了杯奶茶,结果用户疯狂投诉“库存充足却下单失败”。一查Redis监控傻眼了,热点Key被打出火星子。单台Redis扛不住十万并发扣减,请求直接堆积到超时。
凌晨三点拍大腿想到方案:
- 把单个商品库存拆成100份,散落到不同Redis节点
- 客户端随机选个分片操作
- 库存总量=所有分片值之和
异步化救命
第二天压测时数据库又报警了。虽然拦截了80%无效请求,但剩下两万笔/秒写库还是顶不住。赶紧把下单流程拆成两段:
- Redis扣减成功后,先丢进Kafka队列
- 消费者慢慢往数据库落库存
- 前端显示“订单处理中”
最终效果验证
大促当天蹲在监控大屏前啃指甲:
- Redis集群分片值波浪状下降,平稳得很
- Kafka积压消息始终保持在五千以内
- 数据库写连接池使用率没超过30%
- 超卖归零!客服工单量暴跌90%
血泪经验总结
核心难题解法三要素:1)别信客户端请求量;2)用中间件削平流量尖刺,像快递柜取件不堵仓库;3)能异步的步骤坚决拆出去。现在看那些用Go写库存服务的公司,十家有八家还在用*硬扛,想想就替他们膝盖疼。
还没有评论,来说两句吧...