Redis使用单线程的IO复用模型。
服务器需要处理两类事件:
文件事件(file event): 处理与客户端的socket连接
事件事件(time event): 处理服务器中需要定时执行的操作
文件事件(file event)
文件事件处理器(file event handler)
使用I/O多路复用程序来监听多个socket
I/O多路复用程序复杂监听多个套接字,并向文件事件分派器传送那些产生了事件的套接字
I/O多路复用程序总是会将所有产生事件的套接字都放到一个队列里,然后通过这个队列,以有序、同步、每次一个套接字的方式向文件之间分派器传送套接字
Redis I/O复用--->通过包装常见的select,epoll,evport,kqueue 这些IO多路复用函数实现
时间事件:
Redis的时间事件分为以下两类:
1)定时事件:让一段程序在指定事件之后执行一次
2)周期性事件:让一段程序每隔指定时间执行一次
比如:serverCron是redis每隔100ms执行的一个时间事件
serverCron
负责定期对自身的资源和状态进行检查和调整
比如:统计服务器的各类信息,如:时间,内存占用,数据库占用
清理过期键值对
关闭和清理连接失效的客户端
尝试进行AOF或RDB持久化操作
Redis通过无序链表来保存时间事件
新的时间事件总是插入到表头
文件时间和时间事件之间是合作关系,服务器会轮流处理这两种事件,并且处理事件的过程中不会发生抢占。
事件的调度由 aeProcessEvents负责:
伪代码如下:
def aeProcessEvents():
//获取到达时间离当前事件最近的时间事件
time_event = aeSearchNearestTimer()
//计算该时间时间距离到达还有多少秒
remained_time = time_event.when - unix_ts_now()
//如果事件已经到达,那么remained_time可能为负数,将他设为0
if(remained_time<0)
remained_time = 0
//根据remained_time的值,创建timeval结构
timeval = create_timeval_with_ms(remained_time)
//阻塞等待文件事件产生,最大阻塞时间由timeval决定
//如果remained_ms = 0,那么aeApiPoll调用后马上返回,不阻塞
//时间一到就不等socket了!!
aeAipPoll(timeval)
//处理已经产生的文件事件
processFileEvents()
//处理所有已经到达的时间事件
processTimeEvents()