Redis缓存终于突破瓶颈,性能提升明显,效果比预期还要好
- 问答
- 2026-01-14 14:49:37
- 3
(来源:某电商平台技术团队博客分享)
我们平台的商品详情页,一直以来都是个让人头疼的问题,尤其是遇到大促活动,618”或者“双十一”的时候,海量的用户同时涌进来,疯狂点击查看各种商品,那时候,负责承载这些页面数据的Redis缓存服务器,CPU使用率常常飙升到90%以上,像个发高烧的病人,响应时间也变得非常不稳定,有时候一个简单的读取操作都要几百毫秒,页面加载转圈圈转得用户都没了耐心,更糟糕的是,偶尔还会出现缓存雪崩的情况,就是大量缓存同时失效,导致请求直接砸到了后端的数据库上,数据库差点就被打挂了,整个页面都打不开,那真是技术人员的噩梦,我们之前也尝试过一些常规的优化手段,比如给不同的缓存键设置不同的过期时间,避免同时失效,或者加一些本地缓存来分担压力,但效果都不太理想,感觉就像是给一个快要溢出的水池子这里堵一下那里补一下,根本问题没解决。

(来源:同一团队资深工程师内部技术复盘会议记录)
问题的根源,我们后来花了很长时间分析,发现比想象的要复杂,我们的商品数据模型非常复杂,一个商品信息里包含了基础信息、库存、价格、促销活动、商家信息、用户评价汇总等等几十个字段,但用户每次访问时,真正需要的数据可能只是其中一部分,可我们为了图省事,早期设计是把整个商品对象序列化成一个大大的JSON字符串,然后一股脑地塞进Redis里,用一个键来存储,每次读取,不管你要不要,都是把这个大家伙整个取出来,再反序列化,读取的时候浪费网络带宽,解析的时候消耗CPU,这就像是你去超市只想买一瓶水,结果售货员非得把整个货架都搬给你,费力不讨好,我们的缓存键设计得太简单了,就是简单的“product_id:123”这种模式,当我们需要根据不同的条件来查询商品列表,某个分类下价格从低到高的商品”,或者“满减活动的热销商品”,Redis就无能为力了,因为这些复杂的查询不是它的强项,最终还是得去麻烦数据库,大量的这种列表查询,也是拖慢缓存性能的元凶之一。

(来源:该团队新架构设计方案文档)
意识到问题的核心后,我们决定不再小打小闹,而是对缓存的使用方式做一个比较大的改造,我们称之为“缓存结构扁平化”和“查询索引化”,这个名字听起来可能有点唬人,但道理其实很简单,所谓“扁平化”,就是不再把商品所有信息揉成一个“大面团”,而是拆分开,我们把商品的基本信息(标题、图片、描述)存成一个键值对,把实时变动的库存和价格存成另一个键值对,把促销活动信息再存成单独的键值对,这样,当用户打开商品页时,前端其实会发起多个请求,分别获取不同类型的数据,虽然请求次数变多了,但每个请求要传输和处理的数据量变小了,而且不同的数据可以设置不同的过期策略,比如价格库存这种变化快的,过期时间短一些;商品描述这种不变的,过期时间长一些,这样一来,Redis处理的都是轻量级的数据包,压力自然就小了。
那“查询索引化”又是什么呢?就是为了解决复杂查询的问题,我们利用Redis自带的有序集合(Sorted Set)数据结构,来帮我们建立一些简单的“索引”,我们要做“手机分类下按销量排序”的列表,我们就在Redis里维护一个有序集合,集合的名字代表这个查询条件,集合里的每个成员就是商品ID,而分数就是它的销量,当我们需要这个列表时,直接从这个有序集合里取就行了,速度快得惊人,完全不用去查数据库,这需要我们在商品销量更新时,同步去更新这个有序集合里的分数,这增加了一些代码的复杂性,但为了性能,这笔买卖非常划算。
(来源:团队上线后性能监控数据报告)
这套新方案上线之后,效果可以说是立竿见影,我们通过监控系统看得清清楚楚,最直观的就是Redis服务器的平均CPU使用率,从之前动不动就80%、90%,现在稳稳地降到了30%左右,高峰时段也就冲到50%,留下了充足的冗余空间,我们再也不用提心吊胆地看着监控屏幕了,缓存的平均响应时间从原来的平均几十毫秒,下降到了个位数毫秒,几乎就是瞬间响应,前端页面的加载速度提升了40%以上,用户反馈说现在刷页面“丝滑”多了,由于我们拆分了大Key,网络带宽的占用也减少了很多,最重要的是,因为引入了基于有序集合的查询“索引”,很多原本需要查询数据库的复杂列表页面,现在直接从Redis里就搞定了,数据库的压力骤减,之前令人担忧的缓存雪崩风险也大大降低了,这次优化,可以说是我们近期做的投入产出比最高的一次技术改进,效果确实比我们最开始预想的还要好,整个团队都备受鼓舞。

本文由颜泰平于2026-01-14发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://waw.haoid.cn/wenda/80606.html
