简单缓存逻辑
缓存穿透
如果去请求一条不存在的key,那么缓存和数据库都不存在这条记录,每次请求都会打到数据库上,这叫做缓存穿透(可以用来攻击)。
避免
- 缓存空值
可以为这些key对应的值设置为null 丢到缓存里面去。后面再出现查询这个key 的请求的时候,直接返回null 。 - BloomFilter
在海量数据中,布隆过滤器里头可以选缓存数据库到底有什么key。
在缓存之前在加一层 BloomFilter ,在查询的时候先去 BloomFilter 去查询 key 是否存在,如果不存在就直接返回,存在再走查缓存 -> 查 DB
缓存击穿
在高并发系统中,大量请求查询一个key,这个key又刚好失效,那么就会有大量的数据打到数据库中。
解决
可以在第一个查询数据的请求上使用一个 互斥锁来锁住它。
其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。(可以利用guava中的机制,第一个请求阻塞等待,其他请求先获取旧的数据,等新的数据获取到后更新)
缓存雪崩
当某一时刻发生大规模的缓存失效的情况,比如你的缓存服务宕机了,会有大量的请求进来直接打到DB上面。结果就是DB 扛不住,挂掉。
解决
- 使用集群缓存,保证缓存服务的高可用
- Hystrix限流&降级
- 开启Redis持久化机制,尽快恢复缓存集群