前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《Redis设计与实现》读书笔记(十七) ——Redis时间事件与事件调度 (原创内容,转载请注明来源,谢谢)

《Redis设计与实现》读书笔记(十七) ——Redis时间事件与事件调度 (原创内容,转载请注明来源,谢谢)

作者头像
用户1327360
发布2018-03-07 16:00:24
1.4K0
发布2018-03-07 16:00:24
举报
文章被收录于专栏:决胜机器学习决胜机器学习

《Redis设计与实现》读书笔记(十七) ——Redis时间事件与事件调度

(原创内容,转载请注明来源,谢谢)

一、时间事件

1、概述

redis的时间事件分为两类,一类是定时事件,在某个时刻执行;另一类是周期性事件,每隔一段时间执行一次。

时间事件由三部分组成——全局id,标识事件,新的事件比旧的事件id大;unix毫秒级时间戳,记录时间事件的到达时间;事件处理器,时间事件到达时调用相应的处理器进行处理。

一个时间事件是定时还是周期性,取决于其返回值:如果返回的是AE_NOMORE,表示其是一次性的事件,即定时的,执行完毕后redis会将其删除;如果返回的不是该结果,则表示是周期性事件,服务器会根据返回值,更新unix毫秒级时间戳,这样当下一次时间到达时又会执行该事件。

2、实现

redis将所有的时间事件放在一个无序链表中,当时间事件执行器执行时,会遍历整个链表,将所有已到达执行时间的事件调用相应的时间事件处理器进行处理。

虽然是无序链表,但是由于新的时间事件总是插入到表头,因此表头总是最新的时间事件。

无序链表结构如下图:

采用无序链表,是指链表的元素不按照when的先后进行排序,而是强制遍历整个链表,确保所有到达执行时间的事件都能被执行。

在目前的情况下,redis只使用serverCron函数作为时间事件,相当于仅有一个时间事件,因此这个链表可以简化为一个指针。

流程如下:

1)遍历服务器中所有的时间事件。

2)检查每个事件是否到达执行时间,对于已经到达的,执行事件,并获取返回值。

3)如果返回的是AE_NOMORE,表示是定时事件,则服务器删除该事件;否则表示其是周期性事件,服务器会更新事件的when属性,标记下一次执行时间。

3、serverCron函数

redis目前仅使用serverCron函数作为时间事件,即目前仅有这一个时间事件。该时间事件主要进行以下操作:

1)更新redis服务器各类统计信息,包括时间、内存占用、数据库占用等情况。

2)清理数据库中的过期键值对。

3)关闭和清理连接失败的客户端。

4)尝试进行aof和rdb持久化操作。

5)如果服务器是主服务器,会定期将数据向从服务器做同步操作。

6)如果处于集群模式,对集群定期进行同步与连接测试操作。

redis服务器开启后,就会周期性执行此函数,直到redis服务器关闭为止。默认每秒执行10次,平均100毫秒执行一次,可以在redis配置文件的hz选项,调整该函数每秒执行的次数。

二、事件调度与执行

由于redis服务器同时存在文件事件和时间事件,因此必须对这两个事件进行调度,决定何时处理文件事件,何时处理时间事件,以及花费多少时间处理这两类事件。

1、事件调度执行流程

事件的调度和执行由ae.c/aeProcessEvents函数负责,执行流程如下:

1)启动服务器,初始化服务器,一直处理事件,循环下面的2~6步骤,直到服务器关闭。服务器关闭会执行相关的清理操作。

2)获取到达时间距离当前时间最近的时间事件,计算到达时间,单位是毫秒,假设结果是x毫秒。

3)如果时间已经到达,则x是负数,将x置成0。

4)如果x不是0,则程序阻塞,等待文件事件的产生,再进入下一步,其中程序阻塞的最大等待时间是x毫秒,因为即使x毫秒内都没有文件事件的产生,但是x毫秒后必然有时间事件需要执行,因此不能继续阻塞;如果x是0,即已经有时间事件到了需要执行的时候,则程序不阻塞,直接进入下一步。

5)处理所有已经产生的文件事件。

6)处理所有已经产生的时间事件。

2、事件调度执行规则

1)程序等待文件事件的最大阻塞时间,是由到达时间最接近当前时间的时间时间决定,即避免了程序对时间事件的不断轮询,又保证阻塞时间不会太长。

2)由于文件事件的发生,是由客户端决定,即完全随机的。因此程序处理完一个文件事件后,如果没有新的待处理的文件事件,且还没到达最近的时间事件的执行时间,则程序会继续阻塞,直到达到最近的时间事件的时间,或期间有新的文件事件。

3)文件事件和时间事件都是同步、有序、原子的执行,执行一个事件的时候,其他事件会阻塞等待,不会发生事件的抢占。两类事件处理器都会减少程序的阻塞时间,并在有需要的时候主动让出执行权,避免事件的饥饿等待。

例如:文件事件的命令回复处理器,如果内容太多,写入的字节数超出预设的常量,则处理器会自动break,留下剩余的内容下一次再写;时间事件中会将耗时的rdb持久化、aof重写等操作,通过创建子进程,由子进程执行。

4)由于都是优先处理文件事件,后处理时间事件,且处理过程不会发生事件抢占,因此时间事件的实际执行时间,有可能比设定的执行时间稍晚一些。

执行示例如下图:

在等待下一个时间事件的过程中,程序处理了两个文件事件。其中第85毫秒,由于还没到时间事件的执行时间,而有文件事件,因此处理文件事件。由于文件事件处理完毕后是在130毫秒,则时间事件只能在131毫秒执行,比预设的100毫秒晚了31毫秒。

三、总结

1、redis服务器是事件驱动程序,事件分为文件事件和时间事件。

2、文件事件处理程序是基于Reactor的网络通信程序,是对套接字操作的抽象,每当套接字变成可应答、可读、可写的时候,相应的文件事件就会产生。

3、文件事件分为读事件(AE_READABLE)和写事件(AE_WRITEABLE)两类。

4、时间事件分为定时事件和周期性事件,当前redis只有周期性事件,且周期性事件中只有一个事件——serverCron函数,该函数默认每秒执行10次,可以通过配置文件修改每秒执行次数。

5、文件事件和时间事件是合作关系,服务器会轮流处理两个事件,事件不会发生抢占。由于通常先处理文件事件,因此时间事件的实际执行时间有可能比预设时间稍晚。

——written by linhxx 2017.09.06

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-09-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 决胜机器学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档