Redis源码篇(3)——事件循环与io模型

ae

redis是一种典型的reactor设计模式。redis中的任何操作甚至是定时任务的触发都被看成是一个事件,由专门的事件处理器去执行。其内部自己定义了一套ae驱动器ae.hae.c)。
在这里插入图片描述
事件分为文件事件时间事件。像命令的请求,回复都是文件事件。而时间事件则是一种定时触发的事件,如serverCron函数(周期时间事件)、或者过期键的删除(定时时间事件)等。

服务器将所有的时间事件都放在了一个无序链表,每当时间事件执行器运行时,就会遍历整个链表,查找所有已到达的时间事件,并调用相应的事件处理器。定时时间事件在执行的时候会先判断当前时间是否到了,若还没到则会把事件重新加入时间事件链表等待下次的触发。而周期时间事件则是在执行之后会新建一个时间事件并且指定下次触发的时间加入到时间事件链表。

其实无论是时间事件还是文件事件都会用链表去描述。具体见
aeEventLoop
在这里插入图片描述
redis只需循环处理aeEventLoop上的事件即可。而这个循环的入口就是
aeMain
在这里插入图片描述
上图不难看出,事件处理逻辑主要在aeProcessEvents
在这里插入图片描述
除aeMain和aeProcessEvents外,ae其他常用api如下

api说明
aeCreateEventLoop初始化一个事件循环结构体(eventLoop)
aeGetSetSize返回当前setsize的值
aeResizeSetSize改变setsize的值(重新分配空间)
aeDeleteEventLoop删除事件循环,释放内存空间
aeStop停止事件循环,即stop值设为1
aeProcessEvents事件处理逻辑
aeMain事件循环的入口
aeSetBeforeSleepProc注册回调函数,每次主循环在休眠前被调用
aeSetAfterSleepProc注册回调函数,每次主循环在休眠后被调用
aeWait等待指定套接字指定事件的产生
aeCreateFileEvent创建一个文件事件
aeCreateTimeEvent创建一个时间事件

io模型

以客户端发送的命令为例,当套接字收到客服端发来的请求时,会调用aeCreateFileEvent创建一个文件事件并加入到aeEventLoop的事件链表中,由aeMain的事件循环中调用指定的事件处理器去处理该事件。
那么问题来了,事件循环只有一个但客户端可以有多个。换句话说就是redis是如何做到在一个线程里面高效的处理多个客户端的请求的呢?其秘密武器就是多路复用的IO模型——NIO

如下图所示redis内部对不同操作系统所能支持的nio模型做了不同的实现,但对外暴露的api是一致的。这么做的好处就是nio内部的实现对于调用方来说可以是黑盒,无需关心其内部的具体实现。
在这里插入图片描述

api描述
aeApiCreate创建底层apidata(如:epoll_create)
aeApiResize重新分配底层ae事件内存
aeApiFree关闭底层ae并释放内存
aeApiAddEvent发起一个事件
aeApiDelEvent删除一个事件
aeApiPoll查询发生的监听事件
aeApiName返回实现类型(select/epoll/evport/kqueue)

具体什么系统用什么实现,可以在ae.c找到答案
在这里插入图片描述
我们点进去开就能发现linux系统用的是epoll的实现。
在这里插入图片描述
说了这么多,那么到底aeMain和nio有什么关系呢? 其实aeMain是以nio的为基础的事件响应框架,而nio是aeMain的底层实现。
以常用的epoll模型为例,aeCreateFileEvent方法调用了aeApiAddEvent。(aeApiAddEvent正是redis对nio实现所对外暴露的api之一)
在这里插入图片描述
点开aeApiAddEvent可以发现其内部调用的正是epoll_ctl这个系统函数
在这里插入图片描述
同理aeApiPoll调用的是epoll_wait
在这里插入图片描述

好了,那么问题又来了,为什么nio会高效呢?其实现高效的原理是什么?
其实这个高效是操作系统自己实现的(毕竟调用的就是系统函数)。就以epoll为例,其内部的实现有几个关键字:零拷贝(共享内存空间) + 红黑树 + 链表有兴趣的可以去了解一下。

最后再多说一句,除了redis的ae外,像netty、libevent也是一样基于nio实现的事件响应框架。有兴趣也可以去了解一下。

参考文献:《Redis设计与实现》黄健宏著、redis-5.0.14源码

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值