Redis缓存(三)缓存异常的四个方面:数据同步、缓存雪崩、击穿、穿透

先放总结图:

请添加图片描述


异常一:缓存与数据库数据要保持实时一致性

  • 如果Redis为只读模式,更新数据时直接更新MySQL里的数据,同时删除Redis里的旧数据
  • 如果Redis为读写模式,更新数据时Redis和MySQL中都要更新,存在两个问题

1. Redis与数据库中各自操作成功/失败的原子性 ------ 成功/失败问题

解决方案: 消息队列,更新失败后可以再次从消息队列读取更新信息,再次更新;

2. 高并发时,Redis与数据库更新操作间隔时间内有客户端请求,此时得到的数据是旧数据(旧数据可能会被更新到Redis,如果之后不清除Redis,那么往后的请求都将读到Redis中的旧数据)----- 谁先谁后问题

解决方案:延迟双删,更新数据前先删除Redis旧数据 — 更新数据库 — 线程sleep一段时间 —再检查删除Redis中的旧数据(难以计算需要sleep多久,不知道其他线程什么时候将旧数据更新到Redis,sleep时间短了的话,Redis中更新的新数据之后还是会被其他线程改为他们读到的旧数据)

针对问题一二的最终解决方案(强一致性
  • 使用分布式事务锁,对问题一保证原子性,对问题二保证串行性。

在这里插入图片描述


异常二:缓存雪崩(大量数据失效)的原因,Redis中大量数据同时过期 / Redis宕机需要恢复

解决方案
雪崩前预防

  • A) 设置不同过期时间

雪崩后补救

  • A) 服务降级:拒绝非核心数据访问数据库,允许核心数据继续访问数据库获取数据(在数据库能承受的压力内)
  • B) 服务限流:不管是访问核心还是非核心数据,直接限制单位时间内能处理的请求数量
  • C) 服务熔断直接返回异常给客户端,直到Redis恢复后再提供访问请求

异常三:缓存击穿(单个热点数据失效),设置热点数据不过期


异常四:缓存穿透,数据库Redis中均不存在数据,给两者都造成很大压力(业务误删数据或者恶意访问)

解决方案:

A) 发生穿透后在Redis中缓存一个约定好的数值,业务层得到该约定的数值后会得知发生了缓存穿透;

B) 布隆过滤器(bit数组,数组每个元素取0/1)快速确认数据库中是否存在该值:

MySQL插入数据时到布隆过滤器中进行一个映射;

  • 数据X存入数据库时,用N个hash函数计算该数据得到N个数值, i = hash_i(X)
  • 这N个值对过滤器数组长度取模,找到模值对应的数组下标,index_i = i % nums.length
  • 将这几个下标位置的值置1,nums[index_i] = 1’

在这里插入图片描述

查询数据库前,数据X先根据布隆算法求解bit数组,与布隆过滤器中的数组对比,bit数组中有一个元素0/1取值不对就代表数据库中不存在该数据,放弃继续访问数据库。

C) 请求拦截:在拦截器中拦截非法访问

参考文章:

https://time.geekbang.org/column/article/296586

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值