1为什么需要缓存
2缓存带来的问题
有三个经典问题:
3应对方案
这里主要介绍 缓存穿透 的解决方案,先看两幅原理图。
用户请求大致原理图:
用户发出请求后先查缓存,缓存命中则直接返回;
缓存不命中就查数据库,查到后将数据写入缓存并返回给用户。
用户请求缓存和数据库都没有的数据(即缓存穿透,如请求id=-1的数据):
此时缓存基本失去了作用。
常见的解决思路:
将用户请求的不存在的数据也放进缓存,并将值置为null,这样请求走缓存的时候发现结果为null,直接返回即可。
但是需要给缓存中的key设置一个合适的过期时间,否则数据库中有了这样的数据,就会出现 数据不一致 问题。
更好的解决思路:
使用 布隆过滤器(Bloom Filter) 。 它可用于快速判断数据是否存在于某个集合中,借助这个功能,我们可用它来应对缓存穿透。
回顾一下布隆过滤器的两条重要特性:
1. 布隆过滤器判定数据存在,那么它可能存在也可能不存在。
2. 布隆过滤器判定数据不存在,那么它一定不存在。
加上布隆过滤器之后:
用户请求数据,若Bloom Filter返回false,则直接过滤该请求或返回null;若 Bloom Filter 返回true,则查缓存,缓存命中则返回,不命中则查数据库。
Bloom Filter 就好像是加在缓存前的一道 屏障 ,过滤了几乎所有不符合要求的请求。虽然有一定的误判率,即可能有少数通过了 Blo om Filter 的请求在数据库和缓存中也还是不命中,但相比之下,整个系统性能已经大大提升,且 Blo om Filter 的默认误判率只有0.03.
顺带提一下缓存击穿和缓存雪崩的解决方案。
缓存击穿:
在被查询的数据上加互斥锁,一条请求线程拿到锁后其它线程只能等待。
缓存雪崩:
事前:尽量保证整个 redis 集群的高可用性,发现机器宕机尽快补上。选择合适的内存淘汰策略。
事中:本地ehcache缓存 + hystrix限流&降级,避免MySQL崩掉。
事后:利用 redis 持久化机制保存的数据尽快恢复缓存。