环境说明:redis源码版本 5.0.3;我在阅读源码过程做了注释,git地址:https://gitee.com/xiaoangg/redis_annotation
参考书籍:《redis的设计与实现》
文章推荐:
redis源码阅读-一--sds简单动态字符串
redis源码阅读--二-链表
redis源码阅读--三-redis散列表的实现
redis源码浅析--四-redis跳跃表的实现
redis源码浅析--五-整数集合的实现
redis源码浅析--六-压缩列表
redis源码浅析--七-redisObject对象(下)(内存回收、共享)
redis源码浅析--八-数据库的实现
redis源码浅析--九-RDB持久化
redis源码浅析--十-AOF(append only file)持久化
redis源码浅析--十一.事件(上)文件事件
redis源码浅析--十一.事件(下)时间事件
redis源码浅析--十二.单机数据库的实现-客户端
redis源码浅析--十三.单机数据库的实现-服务端 - 时间事件
redis源码浅析--十三.单机数据库的实现-服务端 - redis服务器的初始化
redis源码浅析--十四.多机数据库的实现(一)--新老版本复制功能的区别与实现原理
redis源码浅析--十四.多机数据库的实现(二)--复制的实现SLAVEOF、PSYNY
redis源码浅析--十五.哨兵sentinel的设计与实现
redis源码浅析--十六.cluster集群的设计与实现
redis源码浅析--十七.发布与订阅的实现
redis源码浅析--十八.事务的实现
redis源码浅析--十九.排序的实现
redis源码浅析--二十.BIT MAP的实现
redis源码浅析--二十一.慢查询日志的实现
redis源码浅析--二十二.监视器的实现
redis服务器是一个事件驱动程序,服务器需要处理一下两类事件:
- 文件事件
redis服务器通过套接字与客户端(或者其他redis服务器)进行链接,而文件事件就是对操作套接字的抽象。
服务器与客户端的通信会产生相应的文件事件,服务器通过监听并处理这些事件完成一系列网络操作。 - 时间事件
服务器中的一些操作,需要在给定时间点执行,时间事件就是对服务器这类定时操作的抽象。
一. 文件事件
redis基于reactor模式开发了自己网络事件处理器(文件事件处理器):
- 文件处理使用I/O多路复用(multiplexing)程序来监听多个套接字,根据套接字目前执行的任务来为套接字关联不同的事件处理器;
- 当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作,与操作相应的文件事件就会产生,这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件;
1. 文件事件处理器的构成
文件事件处理器的四个组成部分:套接字、I/O多路复用、文件事件派发器、以及事件处理器;
- 文件事件是对套接字的抽象,每当套接字准备好 连接应答、写入、读取、关闭等操作,就会产生一个文件事件;
- I/O多路复用负责监听多个套接字,I/O多路复用程序会将产生的所有事件放到一个队列里;
然后通过这个队列以有序,以有序、同步、每次一个套接字的方式 传送给文件事件派发器; - 文件事件派发器 接受套接字后,根据套接字产生的事件类型,调用相应的事件处理器;
- 事件处理器就是一个个的函数,函数定义里某个事件发生时,服务器对应的执行的操作;
2. I/O多路复用程序的实现
redis的I/O多路复用程序都是都通过包装常见的select、epoll、evport、kqueue这些常见的I/O多路复用函数库来实现的。
redis为每个I/O多路复用函数都实现来相同的API,所以I/O多路复用程序的的底层是可以互换的。
![](https://i-blog.csdnimg.cn/blog_migrate/c13dc5162c23597c2dd61e179d1636cc.png)
程序会在编译时自动选择性能最好的函数库。选择策略代码位于ae.c
/*
* 选择最优i/o复用策略
* evport > epoll > kqueue > select
*/
/* Include the best multiplexing layer supported by this system.
* The following should be ordered by performances, descending. */
#ifdef HAVE_EVPORT
#include "ae_evport.c"
#else
#ifdef HAVE_EPOLL
#include "ae_epoll.c"
#else
#ifdef HAVE_KQUEUE
#include "ae_kqueue.c"
#else
#include "ae_select.c"
#endif
#endif
#endif
3.事件的类型
I/O多路复用程序可以监听多个套接字的ae.h/AE_READABLE事件和ae.h/AE_WREITEABLE事件;
这两类事件和套接字操作 之间的对应关系如下:
- 当套接字变得可以读时(客户端对套接字执行来write或者close操作),或者有新的可以应答的(acceptable)套接字出现时(客户端对套接字执行来connect操作),套接字产生AE_READABLE事件;
- 当套接字变得可写时(客户端对套接字执行read操作),套接字产生AE_WRITEABLE事件;
4.API
- ae.c/aeCreateFileEvent函数接受一个套接字描述符、一个事件类型以及一个事件处理器作为参数,将给定的套接字的给定事件加入到I/O复用程序的监听范围;
- ae.c/aeDeleteFIleEvent函数 取消对套接字的监听;
- ae.c/aeGetFIleEvents函数 返回套接字的监听类型;
- ae.c/aeWaite 在给定时间内堵塞并等待套接字的事件的产生;
- ae.c/aeApiPoll在给定事件内堵塞 并等待所有被监听的套接字事件的产生
- ae.c/aeProcessEvents文件事件派发器
- ae.c/aeGetApiName 函数返回I/O多路复用程序地秤函数库的名称;如epoll 、select;
5.文件事件的处理器
- 连接应答处理器
networking.c/acceptTcpHandler函数是连接应答处理器,用于对连接服务器的监听套接字客户端进行应答; - 命令请求处理器
networking.c/readQueryFromClient 负责从套接字中读取客户端发送的请求; - 命令回复处理器
networking.c/sendReplayToClient负责将服务器执行命令后,将结果通过套接字返回给客户端;