什么是redis的雪崩和穿透?redis崩溃之后会怎么样?系统该如何应对这种情况?如何处理redis的穿透?
缓存雪崩
![](https://img.haomeiwen.com/i12775885/d8b94d3e999caf48.png)
缓存雪崩的事前事中事后的解决方案
事前:redis高可用,主从+哨兵,redis cluster,避免全盘崩溃
事中:本地ehcache缓存 + hystrix限流&降级,避免MySQL被打死。(事中使用ehcache多做一层缓存 为什么要这样?)
事后:redis持久化,快速恢复缓存数据
![](https://img.haomeiwen.com/i12775885/06320c5c04d59522.png)
好处:数据库绝对不会死,限流组件确保了每秒只有多少个请求能通过。 只要数据库不死,就是说,对用户来说,2/5 的请求都是可以被处理的。只要有 2/5 的请求可以被处理,就意味着你的系统没死,对用户来说,可能就是点击几次刷不出来页面,但是多点几次,就可以刷出来一次。
缓存穿透
![](https://img.haomeiwen.com/i12775885/e9fdc0cbb264230a.png)
这些控制肯定是要设置有效期的,因为它不是正常的数据。他们下一波 黑客别人再发恶意请求怎么办?
答案: 肯定是要做限流+降级的。
缓存击穿
缓存击穿,就是说某个 key 非常热点,访问非常频繁,处于集中式高并发访问的情况,当这个 key 在失效的瞬间,大量的请求就击穿了缓存,直接请求数据库,就像是在一道屏障上凿开了一个洞。
解决方式也很简单,可以将热点数据设置为永远不过期;或者基于 redis or zookeeper 实现互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其它请求才能通过该 key 访问数据。
如何保证缓存与数据库的双写一致性?(双写有没有事务性控制?)
(1) 最经典的缓存+数据库读写的模式,cache aside pattern。cache aside pattern 就以下两条规则
- 读的时候,先读缓存,缓存没有的话,那么就读数据库,然后取出数据后放入缓存,同时返回响应
- 更新的时候,先删除缓存,然后再更新数据库。(这里可以调整一下顺序 ,调整顺序后 可能会出现数据不一致。假设更新缓存失败 就有可能出现这个情况,调整前 可能会出现数据错误,但是不会出现数据不一致)
为什么是删除缓存,而不是更新缓存呢?原因很简单,因为有时候缓存并不是就是数据库的某个数据值,而可能是经过一系列复杂运算得出来的值,另外 有时候这个缓存不会被频繁访问,那么我们可以等用户访问再将数据放到缓存中去。这类似于orm框架中的懒加载思想。需要注意的是 这个方法不适用频繁访问的情况下。因为数据还没更新到DB 就有可能已经有读请求进来了。然后缓存又被放老数据了。
高并发下的数据不一致解决方案:串行化
更新DB数据的时候,根据数据的唯一标识,将操作路由之后,发送到一个jvm内部的队列中(这里的队列当然也可以使用专业的队列MQ)。读取数据的时候,如果发现数据不在缓存中,那么将重新读取数据+更新缓存的操作,根据唯一标识路由之后,也发送同一个jvm内部的队列中,一个队列对应一个工作线程。
这样的话,一个数据变更的操作,先执行,删除缓存,然后再去更新数据库,但是还没完成更新,此时如果一个读请求过来,读到了空的缓存,那么可以先将缓存更新的请求发送到队列中,此时会在队列中积压,然后同步等待缓存更新完成。
这里有一个优化点,一个队列中,其实多个更新缓存请求串在一起是没意义的,因此可以做过滤,如果发现队列中已经有一个更新缓存的请求了,那么就不用再放个更新请求操作进去了,直接等待前面的更新操作请求完成即可。
如果请求还在等待时间范围内,不断轮询缓存 如果发现可以取到值了,那么就直接返回; 如果请求等待的时间超过一定时长,那么这一次直接从数据库中读取当前的旧值。所以 这个时间是要认真去测试的 ,要保证在最坏情况下 依然不会出现问题,实在不行就加机器,让队列分担数据点少一点 。
注意点:
1 轮询时间,这个时间是需要仔细去考量的,因为如果时间大了 会造成用户阻塞时间过长,如果时间小了,假设在读请求进入队列前 有一些耗时的写操作,那么一点轮询时间一过 请求就直接走DB了,一旦请求量过大 就造成了DB的压力。
2 多服务实例部署的请求路由
可能这个服务部署了多个实例,那么必须保证说,执行数据更新操作,以及执行缓存更新操作的请求,都通过nginx服务器路由到相同的服务实例上
redis的并发竞争问题是什么?如何解决这个问题?了解Redis事务的CAS方案吗?
描述:多客户端同时并发写一个key,可能本来应该先到的数据后到了,导致数据版本错了。或者是多客户端同时获取一个key,修改值之后再写回去,只要顺序错了,数据就错了。
![](https://img.haomeiwen.com/i12775885/2d2ba00dda9ecbe8.png)
网友评论