Redis的高并发和快速原因:
1. Redis是纯内存数据库,一般都是简单的存取操作,线程占用的时间很多
时间的花费主要集中在IO上,所以读取速度快。
2. 再说一下IO,Redis使用的是非阻塞IO,IO多路复用,
使用了单线程来轮询描述符,将数据库的开、关、读、写都转换成了事件,减少了线程切换时上下文的切换和竞争。
3. Redis采用了单线程的模型,保证了每个操作的原子性,也减少了线程的上下文切换和竞争。
4. 另外,数据结构也帮了不少忙,Redis全程使用hash结构,读取速度快
还有一些特殊的数据结构,对数据存储进行了优化,如压缩表,对短数据进行压缩存储,再如,跳表,使用有序的数据结构加快读取的速度。
5. 还有一点,Redis采用自己实现的事件分离器,效率比较高,内部采用非阻塞的`行方式,吞吐能力比较大。
一.redis的线程模型
![](https://img-blog.csdnimg.cn/img_convert/17843ab00e51de90e1808eab1798acdb.webp?x-oss-process=image/format,png)
1)文件事件处理器
redis基于reactor模式开发了网络事件处理器,这个处理器叫做文件事件处理器,file event handler。这个文件事件处理器,是单线程的,redis才叫做单线程的模型,采用IO多路复用机制同时监听多个socket,根据socket上的事件来选择对应的事件处理器来处理这个事件。
如果被监听的socket准备好执行accept、read、write、close等操作的时候,跟操作对应的文件事件就会产生,这个时候文件事件处理器就会调用之前关联好的事件处理器来处理这个事件。
文件事件处理器是单线程模式运行的,但是通过IO多路复用机制监听多个socket,可以实现高性能的网络通信模型,又可以跟内部其他单线程的模块进行对接,保证了redis内部的线程模型的简单性。
文件事件处理器的结构包含4个部分:
- 多个socket --与客户端建立连接,负责接收消息
- IO多路复用程序 --用于监听socket,将socket里的信息压入队列
- 文件事件分派器 ---单线程的拿命令去执行
- 事件处理器(命令请求处理器、命令回复处理器、连接应答处理器,等等)。 ----负责处理不同的请求;
多个socket可能并发的产生不同的操作,每个操作对应不同的文件事件,但是IO多路复用程序会监听多个socket,将socket产生的事件放入一个队列中排队,每次从队列中取出一个socket 事件给事件分派器,事件分派器把该事件给对应的事件处理器。
然后一个socket的事件处理完之后,IO多路复用程序才会将队列中的下一个socket的事件给事件分派器。文件事件分派器会根据每个socket当前产生的事件,来选择对应的事件处理器来处理。
2)文件事件
当socket
变得可读时(比如客户端对redis执行write操作,或者close操作),或者有新的可以应答的sccket出现时(客户端对redis执行connect操作),socket就会产生一个AE_READABLE事件
。
当socket变得可写的时候(客户端对redis执行read操作),socket会产生一个AE_WRITABLE事件
。
IO多路复用程序可以同时监听AE_REABLE和AE_WRITABLE两种事件,要是一个socket同时产生了AE_READABLE和AE_WRITABLE两种事件,那么文件事件分派器优先处理AE_REABLE事件,然后才是AE_WRITABLE事件。
3)文件事件处理器
如果是客户端要连接redis,那么会为socket关联连接应答处理器
如果是客户端要写数据到redis,那么会为socket关联命令请求处理器
如果是客户端要从redis读数据,那么会为socket关联命令回复处理器
4)客户端与redis通信的一次流程
![](https://img-blog.csdnimg.cn/img_convert/2810b22aae5330584e367bc56fa8598a.webp?x-oss-process=image/format,png)
在redis启动初始化
的时候,redis会将连接应答处理器
跟AE_READABLE事件
关联起来,接着如果一个客户端跟redis发起连接,此时会产生一个AE_READABLE事件,然后由连接应答处理器来处理跟客户端建立连接,创建客户端对应的socket
,同时将这个socket的AE_READABLE事件
跟命令请求处理器
关联起来。
当客户端向redis发起请求的时候
(不管是读请求还是写请求,都一样),首先就会在socket产生一个AE_READABLE事件
,然后由对应的命令请求处理器来处理。
这个命令请求处理器就会从socket中读取请求相关数据,然后进行执行和处理。
接着redis这边准备好了给客户端的响应数据之后
,就会将socket的AE_WRITABLE事件
跟命令回复处理器
关联起来;
当客户端这边准备好读取响应数据时
,就会在socket上产生一个AE_WRITABLE事件
,会由对应的命令回复处理器来处理
,就是将准备好的响应数据写入socket,供客户端来读取。
命令回复处理器写完之后,就会删除这个socket的AE_WRITABLE事件和命令回复处理器的关联关系。
为什么redis单线程还能效率这么高,并发这么强?
redis是基于非阻塞的IO多路复用机制
,其接收请求后直接压入队列不进行任何处理,无需等待整个请求结束再返回
参考链接:
https://www.jianshu.com/p/2345467b74cf
https://blog.csdn.net/a6833916180/article/details/51260243
https://blog.csdn.net/u012823896/article/details/79240279
![](https://img-blog.csdnimg.cn/direct/67c64049147741939b85489caefbb597.png)
喜欢的朋友记得点赞、收藏、关注哦!!!