专栏首页决胜机器学习《Redis设计与实现》读书笔记(十七) ——Redis时间事件与事件调度 (原创内容,转载请注明来源,谢谢)

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

《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

本文分享自微信公众号 - 决胜机器学习(phpthinker),作者:linhxx

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-09-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 机器学习(七) ——logistic回归

    机器学习(七)——logistic回归 (原创内容,转载请注明来源,谢谢) 一、概述 1、基本概念 logistic回归(logisticre...

    用户1327360
  • 机器学习(二) ——线性回归、代价函数与梯度下降基础

    机器学习(二) ——线性回归、代价函数与梯度下降基础 (原创内容,转载请注明来源,谢谢) 一、线性回归 线性回归是监督学习中的重要算法,其主要目的在于用一个...

    用户1327360
  • 从机器学习学python(二) ——iteritems、itemgetter、sorted、sort

    从机器学习学python(二)——iteritems、itemgetter、sorted、sort (原创内容,转载请注明来源,谢谢) 一、iteritems...

    用户1327360
  • Java EE实用教程笔记----(1)第1章 Java EE平台及开发入门

    最近从图书馆借了本JavaEE实用教程(第3版),打算学习SSH和SSM框架,特此做笔记,以飨读者.

    浩Coding
  • 基础知识 | 每日一练(120)

    小林:老版的 toupper() 和 tolower() 不一定能够正常处理不需要转换的字符参数,例如数字、标点或已经符合请求的字符。在 ANSI/ISO 标准...

    闫小林
  • Shiro 集成 Spring 之授权缓存

    在 手撸 Java Web RBAC 权限管理 中,我们自己实现了一个简易的 RBAC 权限管理框架,且我们也提到了一些缺陷,其中一点就是 : 每次请求需要授...

    一份执着✘
  • ActiveReports 区域报表中的事件介绍

    1、仅触发一次的事件 以下是在报表的处理过程中仅触发一次的所有事件这些事件在报表的处理周期中仅在最开始和结束前触发一次。 ReportStart 该事件在Dat...

    葡萄城控件
  • Android事件处理机制

    用户1907613
  • 穿越“达尔文之海”:荣耀扬起品质“云帆”

    科技营销专家杰佛里摩尔,将企业创新从基础性研究,到大规模产业化之间的距离,称作“达尔文之海”。

    脑极体
  • typora自动图片自动上传到图床

    由于突然发现Typora0.9.84的更新中有一个Support upload images via PicGo or custom commands.

    Dreamy.TZK

扫码关注云+社区

领取腾讯云代金券