redis应用实战(缓存一致性,缓存雪崩)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/madongyu1259892936/article/details/85258648

对于读多写少的高并发场景,我们会经常使用缓存来进行优化。比如说支付的余额展示功能,实际上99%的时候
都是查询,1%的请求是变更(除非是土豪,每秒钟都有收入在不断更改余额),所以,我们在这样的场景下,可
以加入缓存,用户->余额

 Redis缓存与数据一致性问题

那么基于上面的这个出发点,问题就来了,当用户的余额发生变化时,如何更新缓存中的数据?

1.我们是先更新缓存中的数据再更新数据库的数据

2.还是修改数据库的数据,再更新缓存中的数据

这就是我们经常会在面试遇到的问题,数据库的数据和缓存中的数据如何达到一致性?首先,可以肯定的是,
redis中的数据和数据库中的数据不可能保证事务性达到统一的,这个是毫无疑问的,所以在实际应用中,我们都
是基于当前的场景进行权衡降低出现不一致问题的出现概率

更新缓存还是让缓存失效

更新缓存表示数据不但会写入到数据库,还会同步更新缓存; 而让缓存失效是表示只更新数据库中的数据,然后删
除缓存中对应的key。那么这两种方式怎么去选择?这块有一个衡量的指标。

1.如果更新缓存代价很小,那么可以先更新缓存,这个代价很小的意思是我不需要很复杂的计算去获得最新的余额数字等。

2.如果是更新缓存的代价很大,意味着需要通过多个接口调用和数据查询才能获得最新的结果,那么可以先淘汰
缓存。淘汰缓存以后后续的请求如果在缓存中找不到,自然去数据库中检索。

先操作数据库还是先操作缓存?

当客户端发起事务类型请求时,假设我们以让缓存失效作为缓存的的处理方式,那么又会存在两个情况,

1.先更新数据库在让缓存失效

2.先让缓存失效,在更新数据库

更新数据库和更新缓存这两个操作,是无法保证原子性的,所以我们需要根据当前业务场景的容忍性来选择,也就是如果出现不一致的情况下,哪一种更新方式对业务的影响最小,就先执行影响最小的方案。

最终一致性的解决方案

关于缓存雪崩的解决方案

当缓存大规模渗透在整个架构中以后,那么缓存本身的可用性将决定整个架构的稳定性。那么接下来我们来讨论下
缓存在应用过程中可能会导致的问题。

缓存雪崩

缓存穿透是指查询一个根本不存在的数据,缓存和数据源都不会命中,出于容错考虑,如果从数据层查不到数据则不写入缓存,即数据源返回值为null时,不存在null,缓存穿透问题可能会使后端数据源负载加大,由于很多后端数据源不具备高并发性,甚至可能造成后端数据源宕掉

解决方式

1.如果查询数据库也为空,直接设置一个默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访
问数据库,这种办法最简单粗暴。比如,”key” , “&&”。

再返回这个&&值的时候,我们的应用就可以认为这是不存在的key,那我们的应用就可以决定是否继续等待继续访问,还是放弃掉这次操作。如果继续等待访问,过一个时间轮训点后,再次请求这个key,如果取到的值不再是&&,则可以认为这时候key有值了,从而避免了透传到数据库,从而把大量的类似请求挡在了缓存之中。

2.根据缓存数据Key的设计规则,将不符合规则的key进行过滤

采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的BitSet中,不存在的数据将会被拦截掉,从而避免了
对底层存储系统的查询压力

下面一篇文章会讲到布隆过滤器

猜你喜欢

转载自blog.csdn.net/madongyu1259892936/article/details/85258648