遇到的一个缓存穿透故障

在营销系统中,发现因大量并发请求导致数据库连接不足的问题,尤其是在中午时段集中于同一shopId的请求。通过增加数据库连接数和引入本地缓存及本地锁机制,有效防止了数据库连接资源耗尽。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述


在昨天下午,在做业务系统每日巡检的时候,发现营销系统的日志里,出现了209次ERROR,内容如下:

获取商品详情优惠券出错,request:{“productId”:123456,“shopId”:123456,“userId”:123456}
获取商品详情优惠券出错,request:{“productId”:123456,“shopId”:123456,“userId”:123456}
获取商品详情优惠券出错,request:{“productId”:123456,“shopId”:123456,“userId”:123456}

由于是用grep命令找出来,具体是什么报错原因,不清楚,因此用了之前文章shell查找文件显示行号和对应区间的内容里提到的技巧,找出报错的详细内容。

Cause: org.springframework.jdbc.CannotGetJdbcConnectionException,Connection is not available

从日志上看,是获取不到数据库连接了,但是比较奇怪,获取商品详情优惠券这个接口我是加了缓存的,详情请看缓存时间小技巧-随机打散,理论上不太可能有很多的请求穿透到数据库才对呀。因此仔细分析了发生报错的时间和报错的请求入参,发现报错时间集中在中午12点01分这一分钟里,且大部分入参都是同一个shopId的。至于如何用awk统计shopId,请参考awk神器呀

由于店铺的商品详情是按照店铺id作为key来缓存的,一旦某个时间段,店铺的并发请求量一大,而刚好缓存又失效了,如果没有做热key防护,瞬间就有很多请求打到数据库了,造成数据库连接不够用。


解决方案


由于是以店铺id作为key的,只要这个店铺的用户进入到商详,就会调用获取商详优惠券的接口。这种key属于大key,如果我们缓存的key加上userId的话,那就没问题,因为按照userId打散了。不过这样做有个问题,就是缓存的key非常非常多,不建议这么干。

我这边是这么做的:
第一:增加营销系统的数据库连接数,之前才配置了几十个,对于这种C端应用,确实配置少了。
第二:加一个本地缓存,并针对本地缓存,做一个进程级别的本地锁,同一个key并发过来查询,如果从缓存获取不到数据,则放一个请求过去,其他请求继续等待。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值