五、事件
五、事件
redis服务器实际是一个事件循环,事件分为文件事件和时间事件。
文件事件
文件事件就是服务器对套接字操作的抽象,服务器与客户端的通信产生文件事件,服务器通过监听并处理这些文件事件完成一系列网络通信操作;
文件事件处理器以单线程方式运行,但是通过IO多路复用程序同时监听多个套接字,既实现了高性能的网络通信模型,又能与redis服务器中其他同样以单线程方式运行的模块进行对接,保证了redis内部单线程设计的简单性;
文件事件分类
读事件
客户端对连接到服务器的套接字执行write操作或close操作,会生成读事件;
客户端对服务器监听套接字执行connect操作,会生成读事件;
写事件
客户端对连接到服务器的套接字执行read操作,会生成写事件;
文件事件处理器
套接字
每个客户端与服务器对应一个套接字;
IO多路复用程序
通过包装常见的IO多路复用函数库实现;
IO多路复用程序将产生文件事件的所有套接字保存在一个队列中,以有序、每次一个的方式向文件事件分排器传送套接字;
只有在上一个套接字处理完毕之后,才会继续发送下一个套接字;
如果同一个套接字同时产生了读事件和写事件,IO多路复用程序优先发送读事件,然后发送写事件;
文件事件分派器
负责接收IO多路复用程序发送的套接字,并按照不同的事件类型调用相应的事件处理器;
事件处理器
连接应答处理器
负责对连接服务器监听套接字的客户端进行应答;
命令请求处理器
负责从套接字接收客户端发送的命令请求;
命令回复处理器
负责处理命令请求并将得到的结果通过套接字返回给客户端;
时间事件
时间事件分类
定时事件
一段时间后执行一次;
周期性事件
每隔一段时间执行一次;
事件事件的属性组成
id
事件事件id;
when
时间事件的到达时间;
timeProcess
时间事件处理器;
redis服务器中只有serverCron函数一个周期性时间事件,默认每100毫秒执行一次,用于对正在运行的服务器进行维护;
redis服务器会将所有的时间事件放在一个无序链表中,每当时间事件执行器开始运行时,就会遍历无序链表,找到所有已到达的时间事件,然后调用对应的时间事件处理器;
无序链表大多数情况下只有一个时间事件,即使在benchMark模式下,也只有两个时间事件,所以无序链表几乎退化成一个链表使用;
serverCron
更新服务器时间缓存unixtime、mstime;
服务器只有在执行输出打印日志、更新lrulock、决定是否执行持久化操作这类对时间精度要求不高的任务时,才会使用到unixtime、mstime;
服务器在执行添加慢查询日志、为键设置过期时间这类对时间精度要求更高的任务时,仍然会再次执行系统调用,获取最精确的时间戳;
更新服务器lruLock;
默认每十秒更新一次,结合对象redisObject结构中的lru属性计算对象的空转时长;结合客户端redisClient结构中的last_instersection_time计算客户端空转时长;
更新服务器最近一秒执行命令次数;
按照一定的算法抽样估算服务器最近一秒执行命令的次数;
更新服务器内存峰值记录;
处理SIGTERM信号;
redis服务器在启动时,为服务器进程SIGTERM信号关联信号处理器sigtermHandler函数,该函数的作用是在接收到服务器发送的SIGTERM信号时,将服务器状态redisServer结构中的shutdown_asap标识设置为1;
serverCron函数每次执行时,都会检查shutdown_asap标识的值;如果为0,不做任何操作;如果为1,立即关闭这个服务器;
管理客户端资源;
serverCron函数执行时,会调用clientsCron函数对连接到服务器的所有客户端进行两项检查:
1.如果服务器与客户端的连接已经超时,则断开与客户端的连接;
2.如果服务器在处理客户端上一个命令请求时生成的输入缓冲区过大,将输入缓冲区释放,并重新创建一个固定大小的空白缓冲区分配给该客户端;
管理数据库资源
serverCron函数执行时,会调用activeExpireCycle函数,该函数的作用是分多次遍历服务器中的各个数据库,按照算法抽取一部分数据库键进行过期检查,将过期键删除;
执行被延迟的BGREWRITEAOF命令;
服务器在执行BGSAVE命令期间,接收到客户端发送的BGREWRITEAOF命令会被阻塞挂起;
检查持久化操作的运行状态;
服务器状态redisServer结构中的rdb_child_pid、aof_child_pid分别表示执行BGSAVE、BGREWRITEAOF命令时生成的子进程id,用于检查BGSAVE命令或BGREWRITEAOF命令是否正在被执行;
如果rdb_child_pid、aof_child_pid中有一个属性的值不为-1,就会执行一次wait3函数,检查子进程是否有信号发送给当前服务器进程;
如果有信号到达,证明新的RDB文件或新的AOF文件已经生成,就需要用新文件代替旧文件;
如果没有信号到达,证明持久化操作尚未完成,则不做任何操作;
如果rdb_child_pid、aof_child_pid的值均为-1,则执行以下三项检查:
检查是否有被延迟的BGREWRITEAOF命令,如果有,触发该命令的执行;
检查save选项所设置的保存条件是否满足,如果满足且没有正在执行持久化操作,则触发BGSAVE命令的执行;
检查AOF重写条件是否满足,如果满足且没有正在执行持久化操作,则触发BGREWRITEAOF命令的执行;
关闭异步客户端;
服务器处理客户端发送的命令请求时生成的输出缓冲区超过硬性限制的大小,或在规定的时间内始终超出软性限制的大小,客户端会被关闭;
将redisServer结构中的aof_buf缓冲区中的内容写入并同步到AOF文件;
更新serverCron函数的执行次数;
#redis事件#redis 文章被收录于专栏
redis20000字笔记(含思维导图版本-大纲版本)

