Redis缓存Key设置

  • A+
所属分类:Java redis springboot 缓存

背景:

持仓缓存key设置方法及出现问题:

原因分析和解决方案:

Redis缓存注意点:

背景:

春节活动期间,为了提高业务接口的平均响应时间,给业务相关接口加缓存。

持仓缓存key设置方法及出现问题:

缓存key设置方法:key用接口对应的“包名+类名+方法名+userId”设置,例如:

/h5/regular/finance/myfixedfinances(用户定期总资产)缓存key为:com.XXXUserCenterController.getMyFixedProjectInfo10124836;

看起来没什么问题,这样设置的key用用户分开,不同的用户相同的接口不会出现缓存错误的情况。

问题:

1、有多笔定期持仓的情况下,持仓详情缓存的都是第一次打开持仓详情内容;

2、定开持仓二级持仓列表,如果买过多种定开产品,持仓列表缓存错误;

3、历史赎回产品过多,有几页,历史赎回列表缓存错误。

原因分析和解决方案:

问题原因:

最主要的原因就是缓存key设置不合理,为什么呢?

设置缓存key的时候只考虑了接口和用户,没有区别接口相关联的业务特性。我们的持仓业务中,很多业务是共用一个接口的。

问题解决:

按照每个接口的特性,即结合接口的请求参数,结合持仓业务,给持仓接口分类,分别设置接口缓存key;

最后将持仓接口分为以下几类:用户维度的,用户+产品维度;用户+订单维度;用户+分页维度;

最终解决缓存key的问题。

Redis缓存注意点:

缓存击穿:查询一个数据库中不存在的数据,比如商品详情,查询一个不存在的ID,每次都会访问DB,如果有人恶意破坏,很可能直接对DB造成过大地压力。

缓存击穿的解决方案:当通过某一个key去查询数据的时候,如果对应在数据库中的数据都不存在,我们将此key对应的value设置为一个默认的值,比如“NULL”,并设置一个缓存的失效时间,这时在缓存失效之前,所有通过此key的访问都被缓存挡住了。后面如果此key对应的数据在DB中存在时,缓存失效之后,通过此key再去访问数据,就能拿到新的value了。

缓存失效:在高并发的环境下,如果此时key对应的缓存失效,此时有多个进程就会去同时去查询DB,然后再去同时设置缓存。这个时候如果这个key是系统中的热点key或者同时失效的数量比较多时,DB访问量会瞬间增大,造成过大的压力。

缓存失效的解决方案:将系统中key的缓存失效时间均匀地错开,防止统一时间点有大量的key对应的缓存失效;重新设计缓存的使用方式,当我们通过key去查询数据时,首先查询缓存,如果此时缓存中查询不到,就通过分布式锁进行加锁,取得锁的进程查DB并设置缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回缓存数据或者再次查询DB。

热点key:缓存中的某些Key(可能对应用与某个促销商品)对应的value存储在集群中一台机器,使得所有流量涌向同一机器,成为系统的瓶颈,该问题的挑战在于它无法通过增加机器容量来解决。

热点key的解决方案:客户端热点key缓存:将热点key对应value并缓存在客户端本地,并且设置一个失效时间。对于每次读请求,将首先检查key是否存在于本地缓存中,如果存在则直接返回,如果不存在再去访问分布式缓存的机器。将热点key分散为多个子key,然后存储到缓存集群的不同机器上,这些子key对应的value都和热点key是一样的。当通过热点key去查询数据时,通过某种hash算法随机选择一个子key,然后再去访问缓存机器,将热点分散到了多个子key上。

脏数据问题:DB事务性导致回滚,缓存是否回滚,有没有产生脏数据;访问其他服务数据,缓存数据的时候需要判断服务数据是否为正常返回,不能缓存脏数据。

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: