使用Redis时可能出现的问题 以及 解决办法!

前提了解

在讲解这些问题时,我们需要了解使用 Redis 后,数据是如何进行查询的:
前台发送请求,后台先从缓存中取数据,

  • 取到直接返回结果

  • 取不到从数据库中取,

    • 数据库取到就更新缓存,并返回结果
    • 数据库也没取到,就返回空结果!

缓存穿透

问题描述
我们知道当查询数据,在缓存中不存在时,会从数据库中查询!这个时候如果没有查到,会返回空值,而不会将这个不存在的值写入缓存!
当这种(无效的)数据量一大,每次请求都会到数据库中取,会导致数据库压力过大,从而宕机!

解决办法

  1. 进行数据验证
    如:id不小于0,邮箱、电话的格式等等
  2. 缓存无效的key
    如果缓存和数据库中都查不到,使用 SET key value EX 10086;命令写入redis并加上过期时间!(key的格式: 表名:列名:主键名:主键值!)
    此方法存在的问题:只适用于无效key变化不大的情况,加入是恶意攻击,大量不同的无效key,这个方法就行不通了,如果非要用,只能将过期时间设置的短一点!
  3. 布隆过滤器
    在讲这个方法前,我们先来了解一下布隆过滤器这个东西!

布隆过滤器

什么是布隆过滤器?
本质: 布隆过滤器 是一种数据结构,底层是一个 bit(二进制)数组!(和hashmap类似,不同的是这个数组的值是0、1
作用快速查询一个数据是否存在!(适用于大量数据),但存在一点点问题,请看下文!
实现原理:将一个数据映射(初始化)到布隆过滤器上时,要使用多个不同的哈希函数生成多个哈希值,并将对应的bit数组改为1
在这里插入图片描述

  • 思考:为什么是多个hash函数?(为了降低hash冲突)

工作流程:首先对给定元素再次执行哈希计算,得到与添加元素时相同的位数组位置,判断所得位置是否都为 1,如果其中有一个为 0,那么说明元素不存在,若都为 1,则说明元素有可能存在

  • 为什么是可能存在?
    原因很简单,那些被置为 1 的位置也可能是由于其他元素的操作而改变的。比如,元素1 和 元素2,这两个元素同时将一个位置变为了 1(图1所示)。在这种情况下,我们就不能判定“元素 1”一定存在,这是布隆过滤器存在误判的根本原因。

误判率问题:对于误判,我们知道bit数组的长度越长,冲突的可能性越低;但是会消耗空间;所以我们通常会根据经验取一个合适的误判率!只要不超过这个误判率即可!

布隆过滤器解决缓存穿透:
通过上面的了解,我们可以得到如下总结:

  • 优点:二进制组成的数组,占用内存极少,并且插入和查询速度都足够快。
  • 缺点:随着数据的增加,误判率会增加;还有无法判断数据一定存在;另外还有一个重要缺点,无法删除数据
  • 布隆过滤器说不存在,那就一定不存在!如果说存在,则是可能存在!

我们可以将布隆过滤器放在如下位置!
在这里插入图片描述

  • 除了布隆过滤器,还有一个布谷鸟过滤器,大家可以去了解一下!

缓存击穿

问题描述:
对于设置了过期时间的 key,缓存在某个时间点过期的时候,恰好这时间点对这个 Key 有大量的并发请求过来,这些请求发现缓存过期一般都会从后端 DB 加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把 DB 压垮。
某一个热点key过期,导致压力来到数据库!

解决方案:

  • 互斥锁!
    当缓存失效时,不立即去 load db,先使用如 Redis 的 setnx 去设置一个互斥锁,当操作成功返回时再进行 load db 的操作并回设缓存,否则重试 get 缓存的方法。
  • 设置热点key永不过期!物理不过期,但逻辑过期(后台异步线程去刷新)。

Redis相关命令:

  • Expire
    EXPIRE key_name
    设置成功返回 1 。 当 key 不存在或者不能为 key 设置过期时间时(比如在低于 2.1.3 版本的 Redis 中你尝试更新 key 的过期时间)返回 0 。
  • PERSIST(设置为永不过期)
    PERSIST key_name
    过期时间移除成功时,返回 1 。 如果 key 不存在或 key 没有设置过期时间,返回 0 。
  • TTL
    TTL key_name
    当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。 否则,以秒为单位,返回 key 的剩余生存时间。
    注意:在 Redis 2.8 以前,当 key 不存在,或者 key 没有设置剩余生存时间时,命令都返回 -1 。

缓存雪崩

问题描述:
设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到 DB,DB 瞬时压力过重雪崩。与缓存击穿的区别:雪崩是很多 key,击穿是某一个key 缓存。
大量热点key,同一时间过期!

解决办法

  • 互斥锁
  • 热点key永不过期
  • 将过期时间打散
    比如可以在原有的失效时间基础上增加一个随机值,比如 1-5 分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值