菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
197
0

redis-概述

原创
05/13 14:22
阅读数 21688

Redis或者MemoryCache是常用的缓存数据库,redis由于提供更多数据类型、持久化方式、集群功能而更是迅速火热起来。游戏服务器端必用技术,用作高速缓存。
所以redis也基本都是面试中排在MySQL后面的面试题,基本问题例如数据类型,深入问题例如持久化原理和线程模型,更深入的集群和分布式锁实现等都是考察重点。
redis优缺点就不做过多的讲解,百度一大堆。下面就说说针对redis经常碰到的问题。

redis单线程问题
这个被问到了很多次,如果你上来说redis是单线程的,那就基本定位你对redis的了解处于比较浅的层次。
redis执行命令是类似于串行执行的,为的是高效且不用考虑并发的复杂性。但是redis并非单线程的,只是大多数命令是放在一个队列中由一个线程串行执行,而也有一部分命令是并行执行的,例如scan命令就是并行执行的,还有aof持久化的命令也是并行执行。
另外客户端的socket连接管理肯定使用到一个线程的,redis使用的是多路复用机制管理和相应socket事件的,这个事件就可分为连接事件、命令事件、回写事件。这个线程就是io多服复用线程。所有的事件或者叫消息都是写入到一个队列中的。
消息队列的消费者就是一个线程叫做文件事件分配器,把不同的事件分派给对应的处理器去执行,所以就有三个线程来做连接应答处理器来处理客户端建立连接的、命令请求处理器来处理客户端发送上来的命令的、命令回复处理器来处理命令执行完成进行回写的。
所以redis的线程模型和执行过程是:
1.客户端建立socket连接,发送连接请求io多路复用线程将事件放入到命令队列中。
2.事件分派器线程弹出连接请求事件,将该事件分派给连接应答处理器线程进行处理。这就完成了redis客户端的连接。
3.客户端发送命令,io多服复用线程将命令事件放入到命令队列中。
4.事件分配器线程弹出命令请求事件,将事件分派给命令请求处理器线程进行处理,命令处理完成后将结果包装完成后封装成为命令回复事件放入到命令队列中。
5.事件分配器线程弹出命令回复事件,将事件分派给命令回复处理线程,该线程将命令处理结果写入到客户端socket中。
6.客户端请求断开连接,发送断开连接请求io多路复用线程将事件放入到命令队列中。
7.事件分派器线程弹出连接断开请求事件,将该事件分派给连接应答处理器线程进行处理,断开该客户端的socket连接。
看这就用到了5个线程,其实还有其他的线程例如持久化线程、主从同步线程、scan等异步命令线程等,所以说redis是看上去单线程执行的,主要是因为命令处理是串行化的,而不是redis就是个单线程的程序。这个问题也经常是重灾区。

缓存穿透
缓存的作用就是提升访问效率,避免每次都去访问数据库而影响效率。一般就是查询先访问缓存,若有则直接返回,若没有则去访问数据库,若获取到结果放在缓存中供下次查询使用。
缓存穿透主要就是访问一些不存在的数据,这样每次访问缓存都不命中而要去访问数据库,这样就是穿透了缓存直接使用数据库,会增加程序的IO压力,降低程序效率。
解决缓存穿透问题:
1.数据库获取不到记录的,也制作一个特殊缓存,特殊缓存首先值特殊值是空的或者无意义值,另外设置超时回收时间。
2.可以制作布隆过滤器过滤不小请求。

缓存雪崩
redis的string类型缓存可以设置超时时间,超时后即可认为缓存失效不存在。
若大量缓存设置了超时时间,并且超时时间是同一时刻,那么就会导致同时有大量缓存突然失效,然后大量去访问数据库,io暴增导致程序效率极具下降甚至宕机,这就是缓存雪崩。
解决缓存雪崩问题:
1.设置超时时间加一个随机值,这样避免大量缓存同时到达超时时间。
2.极热数据可以在应用层添加一个二级缓存,二级缓存没有的情况下在访问redis缓存,也可以减少redis缓存的压力。

参考资料:
彻底搞懂Redis的线程模型

发表评论

0/200
197 点赞
0 评论
收藏