商品信息缓存用Redis实时更新,性能提升和实战经验分享
- 问答
- 2026-01-11 04:57:09
- 2
今天聊一个电商里特别实际的问题,就是商品信息缓存,大家都知道,为了应对高并发,把商品信息这种经常被读取但又不太频繁变动的数据放到Redis里,能极大提升网站的性能,让页面打开速度飞快,但这又引出一个新问题:当后台修改了商品的价格、库存或者下架了某个商品后,如何让Redis里的缓存也跟着变?如果处理不好,用户看到的就是过期信息,比如已经卖光的商品显示还有库存,或者活动结束了价格还没变回来,这会引发大问题。
最开始,我们可能会用一种最简单粗暴的办法,就是给缓存设置一个过期时间,比如五分钟,这意味着,数据存入Redis后,不管它变没变,五分钟后自动删除,下一次有用户来查询时,发现缓存没了,就去数据库里把最新的数据查出来,再重新塞回Redis,这种方法实现起来特别简单,代码写几行就搞定了。
这个方法有个挺明显的缺点,延迟”,比如运营人员在后台刚把一款热门手机的价格从5999元降到了5599元,这个新价格已经存进数据库了,可是,在接下来的五分钟内,所有来访问的用户,读取的还是Redis里旧的5999元的价格,直到缓存过期,对于促销活动来说,这五分钟的延迟是完全不能接受的,如果这个商品特别热门,访问量巨大,缓存失效的那一刻,所有请求会同时涌向数据库,可能会把数据库压垮,这就是常说的“缓存击穿”。
有没有更及时的办法呢?有,实时更新”,核心思路是:只要数据库里的商品数据一变,我们立刻想办法把Redis里对应的旧缓存给清理掉,这样,下一个用户来查询时,发现缓存是空的,自然就会去数据库取最新数据,然后重新构建缓存,这样用户看到的就是实时更新的信息了。
怎么触发这个“清理”动作呢?实践中常用的是两种方式,我们当时都尝试过。
一种方式是在编写业务代码时,做“双写”,也就是说,无论在后台管理系统的哪里,只要是执行了更新商品信息的操作(比如UPDATE语句),在更新完数据库之后,紧跟着就写一行代码,去把Redis里对应的缓存键(Key)给删除(DEL命令),这种方式很直接,效果也是立竿见影,但它的麻烦在于,需要程序员非常细心,你必须确保每一个能修改商品数据的地方,都无一遗漏地加上了删除缓存的代码,如果某个地方忘了写,那个地方的缓存就不会更新,就成了一个隐患,如果以后增加了新的修改渠道(比如新的API接口),也很容易忘记处理缓存。
另一种方式,也是我们后来觉得更可靠的方式,是借助数据库的“Binlog”,Binlog是MySQL等数据库的一种日志,它会忠实记录下所有对数据库数据造成变更的操作(增、删、改),我们可以用一个独立的程序(比如阿里的Canal)来实时监听MySQL的Binlog日志,当它解析到有商品表的数据发生了变更时,这个程序就自动去Redis里删除对应的缓存,这种方式的好处是,它把缓存更新的逻辑和业务代码完全分开了,无论你的业务代码多么复杂,无论从哪个入口修改的数据,只要最终落到了数据库,Binlog都能抓到,从而触发缓存清理,这就避免了因为程序员疏忽导致的缓存未更新问题,非常可靠,这套机制的搭建和维护会比在代码里直接删除要复杂一些。
除了更新策略,在缓存的使用上也有一些小技巧可以提升性能,当缓存失效后,大量请求同时涌向数据库去查询同一个商品信息,然后又要同时写回Redis,这个过程会有很多重复的数据库查询和网络开销,为了解决这个问题,可以用一个“锁”的机制,只允许一个请求去数据库查询并重建缓存,其他请求暂时等待,等缓存重建好后,直接读取新缓存即可,这样就大大减轻了数据库的压力。
对于商品信息这种结构化的数据,在存入Redis时,是存成JSON字符串好,还是用Redis的Hash结构好呢?这也有讲究,如果每次读取都需要商品的全部信息,那么存成JSON字符串可能更简单高效,一次读写就完成,但如果经常只需要读取商品的部分字段,比如有时候只关心价格和名称,有时候只关心图片和描述,那么用Hash结构存储就更划算,因为可以只读取需要的字段,节省网络传输的数据量。
缓存虽然好,但不能把所有商品都无差别地塞进Redis,毕竟内存是宝贵的,通常我们会设置一个内存使用的上限,并配置淘汰策略(LRU),当内存不足时,自动淘汰掉最近最少使用的缓存数据,对于非常重要的核心商品,可以考虑永不失效,或者设置很长的过期时间,并通过前面说的实时更新机制来保证一致性,确保核心商品的访问永远那么快。
商品信息缓存不是一个“设置了就一劳永逸”的事情,采用实时更新机制,结合Binlog监听这类解耦的方案,再配合一些缓存使用上的优化技巧,才能在保证数据准确性的前提下,真正发挥出Redis的性能优势,让用户体验到流畅快速的购物过程。

本文由钊智敏于2026-01-11发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/78491.html
