redis的缓存穿透如何解决!

redis的高频面试题(开发一定会用到)

	redis的缓存穿透,如何解决?
		所谓的缓存穿透:
			在客户端去查询数据的时候,数据库中没有数据,缓存中也没有,按照redis源码的执行流程
			这就会出现情况-->当客户端发送请求查询数据的时候,并不会直接查询数据库,无论有没有数据都会先去查询redis,如果redis没有,则再查数据库,数据库也没有
			相当于每一次访问请求的时候都会查询两次
			当缓存的次数请求的过多的时候(这个时候redis不会造成宕机),redis就会认为你要搞他,所以redis就会不工作--->造成非常严重的现象,会跳过缓存直接去查询数据库,缓存就相当于没有用,本来缓存是为了提升效率(节省时间的),项目的效率就会大大降低(缓存命中率)
			当直接跳过缓存的时候,数据库的访问量就会增加到非常大的地步,数据库可能就会存在宕机的风险(这就是当黑客开始攻击的时候-->不会直接攻击数据库-->先攻击redis缓存-->redis就会开启自我保护不再工作-->开始大量发送并发攻击数据库)
		这也就是所谓的缓存穿透
			和case穿透很像
			int i = 3;
			switch(i){
				case 1: "今天很开心";
				
				case 2: "今天更开心";

				case 3:
			}
		用网络上获取的数据都会以抓包的形式拿取(tcp/udp协议)
			短连接:从百度爬回来的数据--->只管发(按照规定时间(2s))--->不管项目是否接收到了
			长连接:不但要管发送数据,还要操心数据是否发送到了,如果没有发送到就会一直等待,直到连接超时
			数据包攻击:大量使用并发发送数据包到目标项目,导致目标项目因为性能问题无法接收到任何一个包的数据-->开始给你指定另外一条路(这些正确的数据就会被黑客模拟出来的路所接收到),黑客为了获取数据,还会一直不断的向真正服务器所发送假数据,让其一直处于崩溃状态

附图:redis的缓存同步流程。
在这里插入图片描述

		解决方案有两种:
			一:使用布隆过滤器
				1.首先先规定好redis集群中需要存储什么样的数据(redis中所要存放的数据就是商品信息,那么就规定存入的数据就是商品信息,如果存入的是身份证号信息,就规定是身份证号信息,如果两个都存,那么两个都规定就行了)
					规定好了之后,就会把这些可能出现的文字/字母/数字的哈希值给列举出来(理想状态是找到所有文字/字母/数字的所有可能性),把这些所有的可能性都存到bitmap,当有一个根本不可能的查询过来的时候,直接会被整个bitmap给拦截,这样就节省了查询压力
				哈希值:
					MD5的加密方式使用的就是哈希加密
						现在有一个密码zhangsan1234,这个密码肯定不能以明文暴露,必须要加密
						(shiro就是这么做的)
						把明文密码拆分成char数组--->char[] = {"z","h","a","n"....}
						这个时候就会用到一个算法(散列算法(自己百度))-->散列算法的作用就是计算出char数组中每一个元素的散列坐标值
						z-->124
						h-->dh1
						a-->ffi8
						n-->zzj7
						zhan ---> 124dh1ffi8zzj7
					所产生的这些不规则的数据(字母,符号(-),数字)就是哈希值
				在讲数据库索引的时候是否知道位图索引(bitmap)
				位图:当照片被无限极放大之后就会发现这个照片是一块一块的,那么这一个小块就称之为一个位图
			二:简单粗暴,也非常好用,也比较常用(称之为懒人专用)
				redis中永远不会给你报错空指针(就算你去redis中查询数据,这个key不存在,返回的数据也是nil-->null,并不是会空指针异常)
				当在去查询的时候,无论是数据真的不存在,还是系统出现了各种问题
				这个时候查询的redis是null,然后就会去查询数据库(redis的源码执行流程)
				,但是数据库中也没有数据,那么就会给前端返回一个null值
				但是这个时候如果并发特别大,会造成无用的很多次查询
				当第一个人过来查询的时候,查询缓存和数据库都没有数据,因为返回的是一个"null"
				作为缓存存到数据库中
				-->以user为key的数据-->redis.get("user")-->是null的,又去查询数据库,发现这个数据库返回的也是null-->就把这个"null"-->以user的为key存入到redis中
				redis.set("user","null")(重点注意对象:必须要设置失效时间,当时我所设置的失效时间是10分钟,而且强制规定一定不能大于10分钟)
					那么为什么非得设置的这么短呢?
					(体现严谨性的时候到了)
					有没有一种可能就是当时数据库中没有数据,但是后来数据库中有数据了,如果这个时候缓存中时间设置的非常长,就会一直去走缓存,不会走数据库
					mybatis的二级缓存集成redis,什么时候数据会进入redis中?当实现了一次从数据库中查询数据的时候才会进入redis中
					从redis中查redis.get("user");
					List<User> userListRedis
					从数据库中查select * from user;
					List<User> userListMybatis
					if(userListRedis.size() == userListMybatis.size()) {
						return userListRedis;
					} else{
						把多余的数据以追加的形式存入到redis中
						redis.set("user", JSON.toString(userListMybatis));
						return userListMybatis;
					}
				如果缓存不过期,则就不会去请求数据库,会保护了数据库被请求的并发次数
				解耦!!!!

			Redis-3.2.5--->在两分钟之内4000的并发一直在不断请求redis(而且所查询的数据都是null)
			redis.get("key");--->key一定是不存在的
			1s:4000
			2s:4000
			3s:4000
			应该是在一分多钟的时候就不会再走redis了,会直接抛异常了
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值