作者:奔跑的奶酪二哈

cnblogs.com/xiaowei123/p/13211403.html

二哈最近都没看Redis,现在回来温习下,现在从Redis的三大缓存开始重新探一探有多深有多浅(^▽^)

让我来开始知识的醍醐灌顶把!是时候表演真正的技术了。(哔哔哔哔....)

 铁子们,看在二哈这么卖力的份上,如果觉得本文对你有帮助的话,请动动你的小手,比个❥(^_-)爱心推荐哟。

接下来就开始我们的Redis的三大缓存问题之旅,让我们坐上二哈的小飞船游一游这圣女峰。

在Redis缓存中有三个必须要知道概念:缓存穿透、缓存击穿和缓存雪崩。

缓存穿透

那什么是缓存穿透,它就是指当用户在查询一条数据的时候,而此时数据库和缓存却没有关于这条数据的任何记录,而这条数据在缓存中没找到就会向数据库请求获取数据。它拿不到数据时,是会一直查询数据库,这样会对数据库的访问造成很大的压力。

如:用户查询一个 id = -1 的商品信息,一般数据库 id 值都是从 1 开始自增,很明显这条信息是不在数据库中,当没有信息返回时,会一直向数据库查询,给当前数据库的造成很大的访问压力。

这时候我们要想一想,该如何解决这个问题呢?o(╥﹏╥)o

一般我们可以想到从缓存开始出发,想如果我们给缓存设置一个如果当前数据库不存在的信息,把它缓存成一个空对象,返回给用户。

^_^没错,这是一个解决方案,也就是我们常说的缓存空对象(代码维护简单,但是效果不是很好)。

Redis 也为我们提供了一种解决方案,那就是布隆过滤器(代码维护比较复杂,效果挺好的)。

搜索Java知音公众号,回复“后端面试”,送你一份Java面试题宝典.pdf

那接下来,二哈先解释下这两种方案:

缓存空对象

那什么是缓存空对象呀,二哈!别急,缓存空对象它就是指一个请求发送过来,如果此时缓存中和数据库都不存在这个请求所要查询的相关信息,那么数据库就会返回一个空对象,并将这个空对象和请求关联起来存到缓存中,当下次还是这个请求过来的时候,这时缓存就会命中,就直接从缓存中返回这个空对象,这样可以减少访问数据库的压力,提高当前数据库的访问性能。我们接下来可以看下面这个流程呀~

这时候,我们就会问了呀 ~,如果大量不存在的请求过来,那么这时候缓存岂不是会缓存许多空对象了吗~~~

没错哦!这也是使用缓存空对象会导致的一个问题:如果时间一长这样会导致缓存中存在大量空对象,这样不仅会占用许多的内存空间,还会浪费许多资源呀!。那这有没有什么可以解决的方法呢?我们来想一想:我们可以将这些对象在一段时间之后清理下不久可以了吗 ~

嗯嗯,没错!在想想 Redis 里是不是给我们提供了有关过期时间的命令呀(^▽^),这样我们可以在设置空对象的时间,顺便设置一个过期时间,就可以解决个问题了呀!

setex key seconds valule:设置键值对的同时指定过期时间(s)

在Java 中直接调用 API 操作即可:

redisCache.put(Integer.toString(id), null, 60) //过期时间为 60s

布隆过滤器

那布隆过滤器是不是不是一个过滤器,过滤东西的呀!哎呀,你太聪明了,没错它就是用来过滤东西的,它是一种基于概率的数据结构,主要使用爱判断当前某个元素是否在该集合中,运行速度快。我们也可以简单理解为是一个不怎么精确的 set 结构(set 具有去重的效果)。但是有个小问题是:当你使用它的 contains 方法去判断某个对象是否存在时,它可能会误判。也就是说布隆过滤器不是特别不精确,但是只要参数设置的合理,它的精确度可以控制的相对足够精确,只会有小小的误判概率(这是可以接受的呀 ~)。当布隆过滤器说某个值存在时,这个值可能不存在;当它说不存在时,那就肯定不存在。

这里有个典型的例子呀,来自钱大:

打个比方,当它说不认识你时,肯定就不认识;当它说见过你时,可能根本就没见过面,不过因为你的脸跟它认识的人中某脸比较相似 (某些熟脸的系数组合),所以误判以前见过你。在上面的使用场景中,布隆过滤器能准确过滤掉那些已经看过的内容,那些没有看过的新内容,它也会过滤掉极小一部分 (误判),但是绝大多数新内容它都能准确识别。这样就可以完全保证推荐给用户的内容都是无重复的。

说了这么久,那布隆过滤器到底有什么特点呢:

特点吗,多多来让一个个跟你吹吹(吹到你怀疑人生(≧∇≦)ノ)

  1. 一个非常大的二进制位数组(数组中只存在 0 和 1)

  2. 拥有若干个哈希函数(Hash Function)

  3. 在空间效率和查询效率都非常高

  4. 布隆过滤器不会提供删除方法,在代码维护上比较困难。

每个布隆过滤器对应到 Redis 的数据结构里面就是一个大型的位数组和几个不一样的无偏 hash 函数。所谓无偏就是能够把元素的 hash 值算得比较均匀。

向布隆过滤器中添加 key 时,会使用多个 hash 函数对 key 进行 hash 算得一个整数索引值然后对位数组长度进行取模运算得到一个位置,每个 hash 函数都会算得一个不同的位置。再把位数组的这几个位置都置为 1 就完成了 add 操作。( 每一个 key 都通过若干的hash函数映射到一个巨大位数组上,映射成功后,会在把位数组上对应的位置改为1。)

那为什么布隆过滤器会存在误判率呢?

误判吗?人生哪有不摔跤,只要锄头挥得好,照样能挖到。(咳咳咳,说偏了...)

其实它会误判是如下这个情况:

当 key1 和 key2 映射到位数组上的位置为 1 时,假设这时候来了个 key3,要查询是不是在里面,恰好 key3 对应位置也映射到了这之间,那么布隆过滤器会认为它是存在的,这时候就会产生误判(因为明明 key3 是不在的)。

O(∩_∩)O哈哈~,这时候你会问了:如何提高布隆过滤器的准确率呢?

要提高布隆过滤器的准确率,就要说到影响它的三个重要因素:

  1. 哈希函数的好坏

  2. 存储空间大小

  3. 哈希函数个数

hash函数的设计也是一个十分重要的问题,对于好的hash函数能大大降低布隆过滤器的误判率。

(这就好比优秀的配件之所以能够运行这么顺畅就在于其内部设计的得当。)

同时,对于一个布隆过滤器来说,如果其位数组越大的话,那么每个key通过hash函数映射的位置会变得稀疏许多,不会那么紧凑,有利于提高布隆过滤器的准确率。同时,对于一个布隆过滤器来说,如果key通过许多hash函数映射,那么在位数组上就会有许多位置有标志,这样当用户查询的时候,在通过布隆过滤器来找的时候,误判率也会相应降低。

对于其内部原理,有兴趣的同学可以看看关于布隆过滤的数学知识,里面有关于它的设计算法和数学知识。(其实也挺简单~)

缓存击穿

缓存击穿是指有某个key经常被查询,经常被用户特殊关怀,用户非常 love 它 (^▽^),也就类比“熟客” 或者 一个key经常不被访问。但是这时候,如果这个key在缓存的过期时间失效的时候或者这是个冷门key时,这时候突然有大量有关这个key的访问请求,这样会导致大并发请求直接穿透缓存,请求数据库,瞬间对数据库的访问压力增大。

归纳起来:造成缓存击穿的原因有两个。

(1)一个“冷门”key,突然被大量用户请求访问。

(2)一个“热门”key,在缓存中时间恰好过期,这时有大量用户来进行访问。

对于缓存击穿的问题:我们常用的解决方案是加锁。对于key过期的时候,当key要查询数据库的时候加上一把锁,这时只能让第一个请求进行查询数据库,然后把从数据库中查询到的值存储到缓存中,对于剩下的相同的key,可以直接从缓存中获取即可。

如果我们是在单机环境下:直接使用常用的锁即可(如:Lock、Synchronized等),在分布式环境下我们可以使用分布式锁,如:基于数据库、基于Redis或者zookeeper 的分布式锁。

缓存雪崩

缓存雪崩是指在某一个时间段内,缓存集中过期失效,如果这个时间段内有大量请求,而查询数据量巨大,所有的请求都会达到存储层,存储层的调用量会暴增,引起数据库压力过大甚至宕机。

搜索Java知音公众号,回复“后端面试”,送你一份Java面试题宝典.pdf

原因:

  1. Redis突然宕机

  2. 大部分数据失效

举个例子理解下吧:

比如我们基本上都经历过购物狂欢节,假设商家举办 23:00-24:00 商品打骨折促销活动。程序小哥哥在设计的时候,在 23:00 把商家打骨折的商品放到缓存中,并通过redis的expire设置了过期时间为1小时。这个时间段许多用户访问这些商品信息、购买等等。但是刚好到了24:00点的时候,恰好还有许多用户在访问这些商品,这时候对这些商品的访问都会落到数据库上,导致数据库要抗住巨大的压力,稍有不慎会导致,数据库直接宕机(over)。

当商品没有失效的时候是这样的:

当缓存GG(失效)的时候却是这样的:

对于缓存雪崩有以下解决方案:

(1)redis高可用

redis有可能挂掉,多增加几台redis实例,(一主多从或者多主多从),这样一台挂掉之后其他的还可以继续工作,其实就是搭建的集群。

(2)限流降级

在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量,对某个key只允许一个线程查询数据和写缓存,其他线程等待。

(3)数据预热

数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key。

(4)不同的过期时间

设置不同的过期时间,让缓存失效的时间点尽量均匀。

琐碎时间想看一些技术文章,可以去公众号菜单栏翻一翻我分类好的内容,应该对部分童鞋有帮助。同时看的过程中发现问题欢迎留言指出,不胜感谢~。另外,有想多了解哪些方面内容的可以留言(什么时候,哪篇文章下留言都行),附菜单栏截图(PS:很多人不知道公众号菜单栏是什么)

END

我知道你 “在看”

关于Redis缓存,这三个问题一定要知道!相关推荐

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

    先放总结图: 异常一:缓存与数据库数据要保持实时一致性 如果Redis为只读模式,更新数据时直接更新MySQL里的数据,同时删除Redis里的旧数据: 如果Redis为读写模式,更新数据时Redis和 ...

  2. 关于Redis缓存,这3个问题一定要知道!

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 来源:https://4m.cn/e3JwR 最近都没看R ...

  3. 关于Redis缓存的三个一定要知道的问题哟!

    点击上方「蓝字」关注我们 二哈最近都没看Redis,现在回来温习下,现在从Redis的三大缓存开始重新探一探有多深有多浅(*^▽^*) 让我来开始知识的醍醐灌顶吧!是时候表演真正的技术了.(哔哔哔哔. ...

  4. redis缓存雪崩、击穿、穿透

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.redis缓存雪崩 二.redis缓存击穿 三.redis缓存穿透 前言 主要是介绍一下redis缓存雪崩.击穿. ...

  5. 33:第三章:开发通行证服务:16:使用Redis缓存用户信息;(以减轻数据库的压力)

    说明: (1)声明:这个其中的区别和相同点,要清楚: ● 在[32:第三章:开发通行证服务:15:浏览器存储介质,简介:]中,前端使用[把"用户基本信息"存到Session Sto ...

  6. Redis系列教程(三):如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题

    Java相关的面试都会问到缓存的问题:史上最全Redis面试49题(含答案):哨兵+复制+事务+集群+持久化等,除此之外还会问到缓存雪崩.缓存穿透.缓存预热.缓存更新.缓存降级等不常见的问题,但却是非 ...

  7. Redis 缓存击穿(失效)、缓存穿透、缓存雪崩怎么解决?

    欢迎关注方志朋的博客,回复"666"获面试宝典 原始数据存储在 DB 中(如 MySQL.Hbase 等),但 DB 的读写性能低.延迟高. 比如 MySQL 在 4 核 8G 上 ...

  8. 点赞模块设计:Redis缓存 + 定时写入数据库实现高性能点赞功能

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:solocoder juejin.im/post/5bdc2 ...

  9. 服务运行一段时间,redis缓存就不可用,原来是这个锅!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:陈凯玲 来源:https://urlify.cn/RVzIR ...

最新文章

  1. TensorFlow——入门基础
  2. AWS之EC2搭建WordPress博客
  3. jquery实现checkbox的单选和全选
  4. 【蓝桥杯单片机】红外接收及NEC红外通信协议
  5. android 服务端 servlet webservice,Tomcat 上如何部署Servlet及Android中如何与服务器通信(12页)-原创力文档...
  6. 声乐学习----关于发声的个人解读
  7. 蠎周刊 148: 新年
  8. bug篇——Windows启动redis报错Creating Server TCP listening socket 127.0.0.1:6379: bind: No error...
  9. powerDesigner修改mysql建表语句
  10. 2018年 第九届 蓝桥杯省赛 C/C++ B 组
  11. android手表密码忘了咋办,moto 360手表通过Android 5.0系统自动解锁手机教程
  12. 程序员职场突破——建立优势策略,找到职业突破发力点
  13. 服务器托管双线技术方案
  14. C++二分查找相关函数用法总结
  15. matlab不规则碎片拼接,一种不规则破碎单面图像快速拼接方法
  16. 服务器怎么预防常见的网络攻击
  17. txt文件字符在计算机,(35)在C盘当前文件夹下有一个已经建立好的顺序文件Alph.txt,文件内容为只含有字母的一个字符去、...
  18. 关于RHEL支持T10 PI的情况
  19. pdfbox将多页pdf转成多张长图片
  20. NVIDIA GeForce RTX 2060 配置keras + tensorflow-gpu机器学习环境

热门文章

  1. 70英寸巨屏!小米首款Redmi红米电视来了 售价狠!
  2. 韩国两名男子因偷拍汽车旅馆视频被捕 1600名房客受害
  3. java文件读取的总结_java 读取文件方法的总结
  4. 服务器中anaconda如何修改环境变量,手动添加anaconda3到环境变量中的方法
  5. c语言课程设计--拼图游戏,C语言课程设计_拼图游戏.pdf
  6. 断网python第三方库安装_Python离线断网情况下安装numpy、pandas和matplotlib等常用第三方包...
  7. python清空集合_python集合的操作
  8. python100以内自然数之和_python输出100以内的质数与合数实例代码
  9. 嵌入式Linux入门5:移植总览
  10. 我参与的一个项目总结