文章目录
-
- 1.缓存雪崩
- 2.缓存击穿
- 3.缓存穿透
1.缓存雪崩
场景:同一时间大面积的redis key失效,导致所有的请求打到数据库上
解决办法:
原理:不要让redis key同时失效
- 随机生成redis key的过期时间
- 让热点的key均匀的分布到不同的redis节点上(redis一般都是集群部署)
- 另启定时任务在key快失效的时候进行刷新缓存
- 永久不失效
2.缓存击穿
场景:在大量请求下,某热点key突然失效,导致所有请求都打到数据库上
解决办法:
-
key永远不过期
-
分布式锁(单体应用可以使用数据库互斥锁实现,并将查询结果回写到redis)
3.缓存穿透
场景:恶意攻击者专门访问数据库中不存在的数据,导致穿过redis直接打到数据库上
如:id=-1的请求
解决办法:
-
将这个参数查到的数据缓存到redis,当他下次请求时就可以返回redis中的缓存数据了(不同参数效果不佳)
-
判断id是否是合理值,如是否>0,小于0直接返回return
-
通过ip限流(对方可能会更换ip,效果不佳)
-
布隆过滤器(有机会介绍)
附:
reids 常问面试题:
1.redis 是单线程还是多线程?
答:单线程
2.redis是单线程为什么那么快?
答:
- redis 是基于内存的,内存的访问速度很快,减少磁盘i/o
- 正因为是单线程,避免了多线程的上下文切换和资源消耗
- redis采用非阻塞i/o多路复用机制
- 灵活多样的数据结构
- 持久化(持久化似乎和redis的速度快并没有直接关系,但是这保证的redis数据的安全性和可靠性,也起到数据备份的作用)
3.什么事i/o多路复用机制?
用户首先将需要进行io操作的socket添加到select中,然后阻塞等待select系统调用返回。当数据到达时,socket被激活,select函数返回。用户线程正式发起read请求,读取数据并继续执行。这样用户可以注册多个socket,然后不断地调用select读取被激活的socket,redis服务端将这些socke置于队列中,然后,文件事件分派器,依次去队列中取,转发到不同的事件处理器中,提高读取效率。
采用多路 i/o 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 io 的时间消耗),多路i/o复用模型是利用 select、poll、epoll 可以同时监察多个流的 i/o 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 i/o 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作,从而提高效率。