首页 > 数据库 >Redis之缓存穿透、缓存击穿、缓存雪崩及其解决方法

Redis之缓存穿透、缓存击穿、缓存雪崩及其解决方法

时间:2023-04-10 18:33:54浏览次数:48  
标签:缓存 Redis 布隆 查询 雪崩 key 过滤器

原文地址:https://mp.weixin.qq.com/s?__biz=MzU2MDY0NDQwNQ==&mid=2247483949&idx=1&sn=6c643858d50cee4f9a2cac8ce838baff&chksm=fc05aa77cb722361dc3e3eb2b74f4d68308f7dc1d12e04dc4444a0d2595dc9e484ef318e93ce&scene=27

 

什么是缓存穿透

缓存穿透是指查询一个缓存中和数据库中都不存在的数据,导致每次查询这条数据都会透过缓存,直接查库,最后返回空。当用户使用这条不存在的数据疯狂发起查询请求的时候,对数据库造成的压力就非常大,甚至可能直接挂掉。这种情况的流程就变成下图这样了:

图片

 

 

缓存穿透解决方案

解决缓存穿透的方法一般有两种,第一种是缓存空对象,第二种是使用布隆过滤器。

第一种方法比较好理解,就是当数据库中查不到数据的时候,我缓存一个空对象,然后给这个空对象的缓存设置一个过期时间,这样下次再查询该数据的时候,就可以直接从缓存中拿到,从而达到了减小数据库压力的目的。但这种解决方式有两个缺点:(1)需要缓存层提供更多的内存空间来缓存这些空对象,当这种空对象很多的时候,就会浪费更多的内存;(2)会导致缓存层和存储层的数据不一致,即使在缓存空对象时给它设置了一个很短的过期时间,那也会导致这一段时间内的数据不一致问题。

第二种方案是使用布隆过滤器,这是比较推荐的方法。所谓布隆过滤器,就是一种数据结构,它是由一个长度为m bit的位数组与n个hash函数组成的数据结构,位数组中每个元素的初始值都是0。在初始化布隆过滤器时,会先将所有key进行n次hash运算,这样就可以得到n个位置,然后将这n个位置上的元素改为1。这样,就相当于把所有的key保存到了布隆过滤器中了。

举个例子,比如我们一共有3个key,我们对这3个key分别进行3次hash运算,key1经过三次hash运算后的结果分别为2/6/10,那么就把布隆过滤器中下标为2/6/10的元素值更新为1,然后再分别对key2和key3做同样操作,结果如下图:

图片

 

 

这样,当客户端查询时,也对查询的key做3次hash运算得到3个位置,然后看布隆过滤器中对应位置元素的值是否为1,如果所有对应位置元素的值都为1,就证明key在库中存在,则继续向下查询;如果3个位置中有任意一个位置的值不为1,那么就证明key在库中不存在,直接返回客户端空即可。如下图:

图片

 

 

当客户端查询key4时,key4的3次hash运算中,有一个位置8的值为0,就说明key4在库中不存在,直接返回客户端空即可。

所以,布隆过滤器就相当于一个位于客户端与缓存层中间的拦截器一样,负责判断key是否在集合中存在。如下图:

图片

 

 

布隆过滤器的好处就是解决了第一种缓存空值的不足,但布隆过滤器也存在缺陷,首先,它有误判的可能,比如在上面客户端查询key4的图中,假如key4经过3次hash运算得到的位置分别是2/4/6,由于这3个位置的值都是1,所以,布隆过滤器就认为key4在库中存在,进而继续向下查询了。所以,布隆过滤器判断存在的key实际上可能是不存在的,但布隆过滤器判断不存在的key是一定不存在的。它的第二个缺点就是删除元素比较难,比如现在要删除key2这个元素,那么需要将2/7/11三个位置的元素值改为0,但这样就会影响到key1和key3的判断。

什么是缓存击穿

缓存击穿是指当缓存中某个热点数据过期了,在该热点数据重新载入缓存之前,有大量的查询请求穿过缓存,直接查询数据库。这种情况会导致数据库压力瞬间骤增,造成大量请求阻塞,甚至直接挂掉。

图片

 

 

缓存击穿解决方案

解决缓存击穿的方法也有两种,第一种是设置key永不过期;第二种是使用分布式锁,保证同一时刻只能有一个查询请求重新加载热点数据到缓存中,这样,其他的线程只需等待该线程运行完毕,即可重新从Redis中获取数据。

第一种方式比较简单,在设置热点key的时候,不给key设置过期时间即可。不过还有另外一种方式也可以达到key不过期的目的,就是正常给key设置过期时间,不过在后台同时启一个定时任务去定时地更新这个缓存。

图片

 

 

第二种方式使用了加锁的方式,锁的对象就是key,这样,当大量查询同一个key的请求并发进来时,只能有一个请求获取到锁,然后获取到锁的线程查询数据库,然后将结果放入到缓存中,然后释放锁,此时,其他处于锁等待的请求即可继续执行,由于此时缓存中已经有了数据,所以直接从缓存中获取到数据返回,并不会查询数据库。

图片

 

 

什么是缓存雪崩

缓存雪崩是指当缓存中有大量的key在同一时刻过期,或者Redis直接宕机了,导致大量的查询请求全部到达数据库,造成数据库查询压力骤增,甚至直接挂掉。

图片

 

 

缓存雪崩解决方案

针对第一种大量key同时过期的情况,解决起来比较简单,只需要将每个key的过期时间打散即可,使它们的失效点尽可能均匀分布。

针对第二种redis发生故障的情况,部署redis时可以使用redis的几种高可用方案部署,部署方法可以参考我之前的文章Redis高可用方案—主从(masterslave)架构、Redis高可用架构—哨兵(sentinel)机制详细介绍、Redis高可用架构—Redis集群(Redis Cluster)详细介绍。

除了上面两种解决方式,还可以使用其他策略,比如设置key永不过期、加分布式锁等。

 

标签:缓存,Redis,布隆,查询,雪崩,key,过滤器
From: https://www.cnblogs.com/xingxia/p/redis_interview1.html

相关文章

  • 详解事务模式和Lua脚本,带你吃透Redis 事务
    摘要:Redis事务包含两种模式:事务模式和Lua脚本。本文分享自华为云社区《一文讲透Redis事务》,作者:勇哥java实战分享。准确的讲,Redis事务包含两种模式:事务模式和Lua脚本。先说结论:Redis的事务模式具备如下特点:保证隔离性;无法保证持久性;具备了一定的原子性,但不支持回滚;一致性的概念......
  • 详解事务模式和Lua脚本,带你吃透Redis 事务
    摘要:Redis事务包含两种模式:事务模式和Lua脚本。本文分享自华为云社区《一文讲透Redis事务》,作者:勇哥java实战分享。准确的讲,Redis事务包含两种模式:事务模式和Lua脚本。先说结论:Redis的事务模式具备如下特点:保证隔离性;无法保证持久性;具备了一定的原子性,但不支持回滚;一......
  • Redis学习——基础数据结构
    基础数据结构String唯一的key,获取对应value,不同value结构不同Json序列化为字符串,字符串反序列化为Json常见用途,缓存用户信息动态字符串位图数据结构List相当于LinkedList,链表不是数组。插入很快,定位索引较慢,常用作异步队列(队列、栈都可以)一些慢操作:lindex,ltrim底层数据......
  • nginx更新静态页面客户端缓存不刷新问题
    问题描述:频繁部署静态资源,nginx自带缓存未刷新通过ftp/sftp上传到nginx的静态页(尤其是打包好的单页应用),有可能遇到客户端缓存不刷新的问题,即使重启nginx都无效客户端浏览器也有缓存,一般关闭进程(手机清理,注意某些app光按返回键退回桌面是不会结束进程的),强制刷新网页等方法可以......
  • Redis性能问题诊断以及scan命令耗时分析
    Redis性能问题诊断以及scan命令耗时分析摘要最近公司有项目反馈卡顿.卡顿一小时后自己被拉入群聊.同事已经基本上定位到问题原因.我这边想使用朴素的性能观点进行一下性能问题的拆解为了提高自己.用到的一些脚本echo"info"|redis-cli-p6379-aYourpassword>`da......
  • 三天吃透Redis八股文
    Redis连环40问,绝对够全!Redis是什么?Redis(RemoteDictionaryServer)是一个使用C语言编写的,高性能非关系型的键值对数据库。与传统数据库不同的是,Redis的数据是存在内存中的,所以读写速度非常快,被广泛应用于缓存方向。Redis可以将数据写入磁盘中,保证了数据的安全不丢失,而且Redis......
  • @Cacheable和@CachePut存入redis的数据使用redisTemplate取出时为null的解决
    当使用@Cacheable和@CachePut注解存数据到redis中时如果使用spring默认的rediskey序列化方式时,使用redisTemplate取数据为null@CacheConfig(cacheNames="users")存入redisusers目录下取数据时的key为users::usernamepublicinterfaceUserRepositoryextendsJpaRepos......
  • Redis随笔
    Redis简介Redis是一个开源的key-value存储系统。存储在内存中。相比于Memcached,value类型相对更多,string、list、set、zset、hash。Redis操作都是原子性的,单线程多路IO复用Redis支持各种不同方式的排序。 keys*查看当前库所有keyexistskey判断某个key是否存在typek......
  • MongoDB、Redis、HBase、Cassandra、Elasticsearch、ClickHouse等NoSQL数据库简介及优
    MongoDBMongoDB是一个基于文档的NoSQL数据库,它使用BSON(二进制JSON)格式存储数据。MongoDB支持动态查询,可以轻松地处理非结构化数据。它还支持水平扩展,可以在多个节点上分布数据。优点:灵活性高,支持非结构化数据存储。支持水平扩展,可以在多个节点上分布数据。支持动态查询,可......
  • 【学习笔记】mybatis中的缓存介绍和使用
    文章目录介绍一级缓存和二级缓存让一级缓存失效的方法二级缓存的使用清空或者跳过二级缓存的3种方式介绍什么是缓存?缓存就是存储数据的一个地方(称作:Cache),当程序要读取数据时,会首先从缓存中获取,有则直接返回,否则从其他存储设备中获取,缓存最重要的一点就是从其内部获取数据的速度是......