业务场景:理财(查询可购买产品列表,某产品信息)
需要频繁查询某表的数据,如果每次都去数据库查询,会增加数据库压力,所以在访问数据库前增加一道缓存。
先上图,再来说明
上图所示,对于一般场景(缓存模型),先去访问redis中缓存的信息,避免每次访问数据库;
但如果当我们的缓存key到了失效时间,过期了,redis中无数据,按照设计就要直接去查数据库了,1000个用户、2W个用户如果同时点击理财列表查询接口,就有2W个查询线程会同时去查询数据库,数据库线程池的压力就有点吃不消咯
这时,我们设置2层缓存,初级缓存过期了,但是备份缓存(过期时间久)还在,这时直接返回备份数据给前端,并去查DB更新缓存。
但不能这2W个线程都去查DB更新,所以加了个锁,只允许第一名争锁成功的线程去更新,其他线程争锁失败,那就先拿备份数据回家而不是wait等待第一名更新完。
说明:
初级缓存的key为:
(列表)cache:{tableName}:list:{queryCondition}
(单品)cache:{tableName}:item:{primaryKey}
备份缓存的key为:
(列表)backup:{tableName}:{queryCondition}
(单品)backup:{tableName}:item:{primaryKey}
查询加锁的key为:
(列表)querylock:{tableName}:{queryCondition}
(单品)querylock:{tableName}:item:{primaryKey}
对于热点数据的高频次访问,除了数据库前加缓存,查询化服务也应该单独部署机器以降低影响正常业务的概率,并且查询走单独的数据库(备份库仅供查询)
目的:尽一切可能降低查询业务对正常业务的影响