缓存雪崩怎么解决?
如果缓存因为某个原因不可用,导致大量请求涌向数据库,可能会导致数据库崩溃。
缓存雪崩目前主要有两种方案:
1. 使用集群
集群部署缓存,当一台宕机时,其他机器仍能提供缓存服务
2. Hystrix
熔断器,起到熔断,降级,限流三个作用。
通过熔断器可以保证当缓存服务不可用时,服务仍能使用,但返回的数据是特定的(此处返回结果与集群的不一样,集群的结果仍然是正确的,而此时则是一个预定的值)
熔断:hystrix是一个Java类库,采用命令模式.每一项服务的请求都有各自的处理器.所有的请求都要首先经过自己的处理器.处理器会记录请求失败率,当失败率达到一个预定值时,就会拒绝该服务随后的所有请求,并直接返回一个预设的值.这就是熔断.
限流:当经过一段时间之后, Hystrix就会放行该服务的部分请求,并统计失败率,若失败率符合预期值,则会完全打开限流开关,若失败率仍然很高,则继续拒绝.这就是限流.
降级:Hystrix直接向那些被拒绝的请求返回一个特定值,就是降级.
缓存一致性如何保证?
(待验证)可以使用类似mysql主从复制的原理去实现.即去跟踪binlog日志文件,然后将该文件写入到一个消息队列中去,再由各个redis服务去消费,从而更新缓存.
缓存穿透如何避免?
缓存穿透是由于数据库中根本不存在查询的数据,导致每次查询都要经过数据库。
造成缓存穿透的主要原因有两点:
- 恶意请求
- 代码逻辑
其主要解决方案主要可分为两种:
1. 缓存空数据
将数据库查询结果为空的key也缓存起来,这样当后续又出现该key时,缓存直接返回空。
此法对于第一种情况的恶意请求其实还是无法起到保护的作用。
2. 布隆过滤
在查询缓存之前再添加一层布隆过滤器 BloomFilter
, 里面存储着数据库的所有key, 这样当一个查询请求过来的时候,会首先经过布隆过滤器,当布隆过滤器中不存在该key时,直接返回null,这样既不用查缓存又不用查数据库.
具体的布隆过滤原理请见后文。
如何保证缓存不同时失效?
可在设置缓存的过期时间时,给每个过期时间都加上一个随机值,防止在同一时间缓存大量失效。
布隆过滤原理
概述: 当数据量很大时,使用传统的map来存储数据会导致内存占用很大,此时布隆过滤器可以以较小的内存使用量达到很快的查询速度,其插入和检索的时间复杂度都是O(k)(k是哈希函数的个数)
实现原理: 布隆过滤器主要使用一个超大的位数组和k个哈希函数来进行.位数组的每一项全部都初始化为0.
当在插入数据时,首先根据多个哈希函数计算相应的哈希值,然后分别映射到位数组上的相应的点,并将这些位置上的点全部置为1.如此插入结束.
当在检索数据的时候,首先根据多个哈希函数计算相应的哈希值,然后分别映射到位数组上的点,若这些位置上的点的值全部为1,则表示该key存在,否则不存在.
当然,当数据量很大时,有可能会导致大部分位上全部都是1,极端情况是所有位置都为1,这就导致误报率很高,这需要一定的权衡利弊,所以布隆过滤不是精确的.
参考文章
- https://juejin.im/post/5aa8d3d9f265da2392360a37