问题:
Redis 是单线程的,怎么实现的多个客户端的链接访问?服务器
Redis服务器是一个事件驱动程序,服务器须要处理一下两类事件:
* 文件事件(file event): Redis服务器经过套接字与客户端(或者其余Redis服务器)进行链接,而文件事件就是服务器对套接字操做的抽象。服务器与客户端(或者其余服务器)的通讯会产生相应的文件事件,而服务器则经过监听并处理这些事件来完成一系列网络通讯操做。
* 时间事件(time event):Redis服务器中的一些操做(好比 serverCon)函数须要在给定的时间点执行,而时间事件就是服务器对这类定时操做的抽象。网络
文件事件
Redis基于Reactor模式开发了本身的网络事件处理器:这个处理器被称为文件事件处理器(five event handler)
* 文件事件处理器使用I/O多路复用(multiplexing)程序来同时监听多个套接字,并根据套接字目前执行的任务来为套接字关联不一样的事件处理器。
* 当监听的套接字准备好执行链接应答(accept),读取(read),写入(write),关闭(close)等操做时,与操做相对应的文件事件就会产生,这时文件事件处理器就会调用套接字以前关联好的事件处理器来处理这些事件。
虽然文件事件处理器以单线程方式运行,但经过使用I/O多路复用程序来监听多个套接字,文件事件处理器既实现了高性能的网络通讯模型,又能够很好地与Redis服务器中其余一样以单线程方式运行的模块进行对接,这保持了Redis内部单线程设计的简单性。并发
文件事件处理器的构成函数
文件事件处理器的四个组成部分,它们分别是套接字,I/O多路复用程序,文件事件分派器(dispatcher),以及事件处理器。性能
文件事件是对套接字操做的抽象,每当一个套接字准备好执行链接应答(accept),写入,读取,关闭等操做时,就会产生一个文件事件。由于一个服务器一般会链接多个套接字,因此多个文件事件有可能会并发地出现。spa
I/O 多路复用程序负责监听多个套接字,并向文件事件分派器传送那些产生了事件的套接字。线程
尽管多个文件事件可能会并发地出现,但I/O多路复用程序老是会将全部产生事件的套接字都放在一个队列里面,而后经过这个队列,以有序(sequentially)、同步(synchronoously)、每次一个套接字的方式向文件事件分派器传送套接字。当上一个套接字产生的事件处理完毕以后(该套接字为事件处理完毕),I/O多路复用程序才会继续向文件事件分派器传送下一个套接字。设计
文件事件分派器接收I/O多路复用程序传来的套接字,并根据套接字产生的事件的类型,调用相应的时间处理器。指针
服务器会执行不一样任务的套接字关联不一样的事件处理器,这些处理器是一个个函数,它们定义了某个事件发生时,服务器应该执行的动做。server
I/O多路复用程序的实现:
时间事件
Redis的时间事件分为如下两类:
* 定时事件:让一段程序在指定的时间以后执行一次。好比说:让程序X在当前时间的30毫秒以后执行一次。
* 周期性事件:让一段程序每隔指定时间就执行一次。好比说:让程序Y每隔30毫秒就执行一次。
一个时间事件主要由如下三个属性组成:
* id: 服务器为时间事件建立的全局惟一ID(标识号)。ID号按从小到大的顺序递增,新事件ID号比旧事件的ID号要大。
* when:毫秒精度的UNIX时间戳,记录了时间事件的到达(arrive)时间。
* timeproc: 时间事件处理器,一个函数。当时间事件到达时,服务器就会调用相应的处理器 来处理事件。
一个时间事件是定时器事件仍是周期性事件取决于时间事件处理器的返回值:
* 若是事件处理器返回ae.h/AE_NOMORE,那么这个事件为定时事件:该事件在达到一次以后会被删除,以后再也不到达。
* 若是事件处理器返回一个非AE_NOMORE的整数值,那么这个事件为周期性事件:当一个时间事件到达以后,服务器会根据事件处理器返回的值,对时间事件的when属性进行更新,让这个事件在一段时间以后再次到达,并以这种方式一直更新并运行下去。好比说,若是一个时间事件的处理器函数返回整数值30,那么服务器应该对这个事件进行更新,让这个事件在30毫秒以后再次到达。
实现:
服务器将全部时间事件都放在一个无序链表中,每当时间事件执行器运行时,它就遍历整个链表,查找全部已到达的时间事件,并调用相应的事件处理器。
无序列表并不影响时间事件处理器的性能
在目前版本中,正常模式下的Redis服务器只使用serverCron一个时间事件,而在benchmark模式下,服务器也只使用两个时间事件。这种状况下,服务器几乎是将无序链表退化成一个指针来使用,因此使用无序链表来保存时间事件,并不影响事件执行的性能。
总结 * Redis服务器是一个事件驱动程序,服务器处理的事件分为时间事件和文件事件两类。 * 文件事件处理器是基于Reactor模式实现的网络通讯程序。 * 文件事件是对套接字操做的抽象:每次套接字变为可应答(acceptable),可写(writeable)或者可读(readable)时,相应的文件事件就会产生。 * 文件事件分为AE_READABLE(读事件)和AE_WRITEABLE事件(写事件)两类。 * 事件时间能够分为定时事件和周期性事件:定时事件只在指定的时间到达一次,而周期性事件则每隔一段时间到达一次。 * 服务器在通常状况下只执行serverCorn函数一个时间事件,而且这个事件是周期性事件。 * 文件事件和时间事件之间是合做关系,服务器会轮流处理这两种事件,而且处理事件的过程当中也不会进行抢占。 * 时间事件的实际处理时间一般会比设定的达到时间晚一些。