八股文骚套路之Redis
缓存雪崩的解决方案
缓存在同一时间大面积的失效,导致大量的请求都直接落到了数据库上,对数据库造成了巨大的压力
缓存服务宕机也会导致缓存雪崩现象
解决方法
针对redis服务不可用的情况
- Redis 集群:采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用
- 多级缓存
针对大量缓存同时失效的情况
- 设置随机失效时间:避免大量缓存同时到期
- 提前预热:针对热点数据提前预热,将其存入缓存中并设置合理的过期时间 (比如秒杀场景下的数据在秒杀结束之前不过期(逻辑过期))。
- 缓存预热的常见实现方式:定时任务和消息队列,Kafka可以异步的进行缓存预热
如何保证缓存和数据库中数据的一致性
- 让缓存失效的时间变短,这样缓存就会很快从数据库从加载数据。(不推荐)
- 增加缓存更新重试机制:针对缓存不可用导致的缓存删除失败,可以引入消息队列实现异步重试,将删除缓存重试的消息投递到消息队列,然后由专门的消费者来重试,直到成功。
缓存击穿(热点key问题)
请求的 key 对应的是热点数据 ,该数据存在于数据库中,但不存在于缓存中,瞬时大量的请求直接打到了数据库上
举个例子:秒杀进行过程中,缓存中的某个秒杀商品的数据突然过期,这就导致瞬时大量对该商品的请求直接落到数据库上,对数据库造成了巨大的压力
解决方案
- 提前预热:提前将热点key存入缓存
- 加锁:在缓存失效之后,通过设置互斥锁确保只有一个请求取查询数据库更新缓存。
- 永不过期(不推荐)
缓存穿透
大量请求的key 不存在于缓存中,也不存在于数据库中
解决方法
- 缓存空值
- 设置布隆过滤器:布隆过滤器可以很方便的判断一个给定数据是否存在于海量数据中。相当于在用户请求和缓存之间添加了一层过滤,将所有可能存在的请求值都存放在布隆过滤器中,当用户请求过来,先判断在不在过滤器中,如果不存在,则直接返回请求参数错误给客户端。
缓存穿透vs缓存击穿
缓存穿透: 请求的key在缓存中不存在,也不存在在数据库中
缓存击穿:请求的key是热点数据,不在缓存中,在数据库中
缓存雪崩vs缓存击穿
缓存雪崩: 缓存中的大量或所有数据失效
缓存击穿: 热点数据不在缓存中(通常是由于缓存中的那份数据已经过期)
解决数据一致性问题常用的缓存读写策略
- 旁路缓存:
- 写:先更新数据库,然后直接删除缓存(数据库优先)
- 读:先读缓存;读不到就读db返回;然后把数据写入缓存
- 适用于读请求较多的场景
- 读写穿透
- 写:先查缓存,缓存中没有直接更新数据库;缓存中存在则先更新缓存,然后缓存同步更新数据库(缓存优先)
- 读:先读缓存;读不到就读db,写入缓存再返回
- 异步缓存写入:
- 类似读写穿透,两者都是由 cache 服务来负责 cache 和 db 的读写。
- 两者区别在于:读写穿透同步更新数据库和缓存;异步缓存写入只更新缓存,异步批量更新数据库
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Protoss想要平静生活!