事件是 Redis 服务器的核心,它处理两项重要的任务:
  • 文件事件

    • 在多个客户端中实现多路复用,接受它们发来的命令请求,并将命令的执行结果返回给客户端。
  • 时间事件
    • 实现服务器常规操作(server cron job)。
 
文件事件

 
  • 读事件
  • 写事件
 
读写事件的定义,是服务器对客户端的套接字操作;
当服务器有数据返回给客户端,此时需要写套接字则是写事件;
当服务器从客户端读取命令,来执行,此时需要读取套接字则是读事件;
 
读事件
读事件标志着客户端命令请求的发送状态。
 
当一个新的客户端连接到服务器时,服务器会给为该客户端绑定读事件,直到客户端断开连接之后,这个读事件才会被移除。
 
读事件在整个网络连接的生命期内,都会在等待和就绪两种状态之间切换:
  • 当客户端只是连接到服务器,但并没有向服务器发送命令时,该客户端的读事件就处于等待状态
  • 当客户端给服务器发送命令请求,并且请求已到达时(相应的套接字可以无阻塞地执行读 操作),该客户端的读事件处于就绪状态
 
写事件
写事件标志着客户端对命令结果的接收状态
 
和客户端自始至终都关联着读事件不同,服务器只会在有命令结果要传回给客户端时,才会为
客户端关联写事件,并且在命令结果传送完毕之后,客户端和写事件的关联就会被移除
 
一个写事件会在两种状态之间切换:
  • 当服务器有命令结果需要返回给客户端,但客户端还未能执行无阻塞写,那么写事件处于等待状态
  • 当服务器有命令结果需要返回给客户端,并且客户端可以进行无阻塞写,那么写事件处于就绪状态。
 
当客户端向服务器发送命令请求,并且请求被接受并执行之后,服务器就需要将保存在缓存内
的命令执行结果返回给客户端,这时服务器就会为客户端关联写事件
 
 
注意:同时关联写事件和读事件
因为半双工的原因,要么执行读事件,要么执行写事件
读事件的优先级高。
 
事件时间

 
时间事件记录着那些要在指定时间点运行的事件,
多个时间事件以无序链表的形式保存在服务器状态中
 
时间事件主要由三个属性组成:
  • when :以毫秒格式的 UNIX 时间戳为单位,记录了应该在什么时间点执行事件处理函数。
  • timeProc:事件处理函数。
  • next指向下一个时间事件,形成链表
 
根据 timeProc 函数的返回值,可以将时间事件划分为两类
  • 如果事件处理函数返回 ae.h/AE_NOMORE ,那么这个事件为单次执行事件:

    • 该事件会在指定的时间被处理一次,之后该事件就会被删除,不再执行。
  • 如果事件处理函数返回一个非AE_NOMORE的整数值,那么这个事件为循环执行事件:
    • 该事件会在指定的时间被处理,之后它会按照事件处理函数的返回值,
    • 更新事件的when属性,让这个事件在之后的某个时间点再次运行,并以这种方式一直更新并运行
 
当时间事件处理器被执行时,它遍历所有链表中的时间事件,检查它们的到达事件(when 属性),并执行其中的已到达事件:
伪代码
def process_time_event(server):
# 遍历时间事件链表
for time_event in server.time_event_linked_list: # 检查事件是否已经到达
if time_event.when >= unix_ts_in_ms(): # 处理已到达事件
handle_time_event(server, time_event)

  

时间事件应用:服务器常规操作
 
服务器需要定期对自身的资源和状态进行必要的检查和整理,
从而让服务器维持在一个健康稳定的状态,这类操作被统称为常规操作(cron job)
 
在 Redis 中,常规操作由 redis.c/serverCron 实现,它主要执行以下操作:
  • 更新服务器的各类统计信息,比如时间、内存占用、数据库占用情况等
  • 清理数据库中的过期键值对。
  • 对不合理的数据库进行大小调整。
  • 关闭和清理连接失效的客户端。
  • 尝试进行AOF或RDB持久化操作。
  • 如果服务器是主节点的话,对附属节点进行定期同步。
  • 如果处于集群模式的话,对集群进行定期同步和连接测试
 
在 Redis 2.6 版本中,程序规定 serverCron 每隔 10 毫秒就会被运行一次。从 Redis 2.8 开始,
10 毫秒是 serverCron 运行的默认间隔,而具体的间隔可以由用户自己调整。
 
事件的执行与调度

 
Redis里面的两种事件呈合作关系,它们之间包含以下三种属性:
  • 一种事件会等待另一种事件执行完毕之后,才开始执行,事件之间不会出现抢占。
  • 事件处理器先处理文件事件(处理命令请求),再执行时间事件(调用 serverCron)
  • 文件事件的等待时间(类 poll 函数的最大阻塞时间),由距离到达时间最短的时间事件决定。
 
这些属性表明,实际处理时间事件的时间,通常会比时间事件所预定的时间要晚,至于延迟的
时间有多长,取决于时间事件执行之前,执行文件事件所消耗的时间
 
根据情况,如果处理文件事件耗费了非常多的时间,serverCron 被推迟到一两秒之后才能执行,也是有可能的。
 
整个事件处理器程序可用用伪代码描述

def process_event():
# 获取执行时间最接近现在的一个时间事件
te = get_nearest_time_event(server.time_event_linked_list) # 检查该事件的执行时间和现在时间之差
# 如果值 <= ,那么说明至少有一个时间事件已到达
# 如果值 > ,那么说明目前没有任何时间事件到达
nearest_te_remaind_ms = te.when - now_in_ms() if nearest_te_remaind_ms <= :
# 如果有时间事件已经到达
#阻 那么调用不塞的文件事件等待函数
poll(timeout=None)
else:
# 如果时间事件还没到达
# 那么阻塞的最大时间不超过 te 的到达时间
poll(timeout=nearest_te_remaind_ms) # 处理已就绪文件事件
process_file_events() # 处理已到达时间事件
process_time_event()
通过这段代码,可以清晰地看出:
• 到达时间最近的时间事件,决定了 poll 的最大阻塞时长。
• 文件事件先于时间事件处理。
 
小结
  • Redis 的事件分为时间事件和文件事件两类。
  • 文件事件分为读事件和写事件两类:读事件实现了命令请求的接收,写事件实现了命令结果的返回。
  • 时间事件分为单次执行事件和循环执行事件,服务器常规操作 serverCron 就是循环事件。
  • 文件事件和时间事件之间是合作关系:一种事件会等待另一种事件完成之后再执行,不会出现抢占情况。
  • 时间事件的实际执行时间通常会比预定时间晚一些
 
 

redis 事件的更多相关文章

  1. Redis事件

    Redis事件 Redis的ae(Redis用的事件模型库) ae.c Redis服务器是一个事件驱动程序,服务器需要处理以下两类事件: 文件事件(file event):Redis服务器通过套接字与 ...

  2. Redis事件管理(二)

    Redis的定时器是自己实现的,不是很复杂.说说具体的实现吧. 定时器的存储维护采用的是普通的单向链表结构,具体节点定义为: /*时间定时器结构体*/ typedef struct aeTimeEve ...

  3. Redis事件管理(一)

    Redis统一的时间管理器,同时管理文件事件和定时器, 这个管理器的定义: #if defined(__APPLE__) #define HAVE_TASKINFO 1 #endif /* Test ...

  4. Redis事件管理(三)

    Redis的事件管理和定时器的管理都是自己来实现的,Redis的事件管理分为两部分,一部分是封装了系统的异步事件API,还有一部分是在这基础上封装了一个通用的事件管理器,根据具体的系统来决定具体使用哪 ...

  5. Redis事件订阅和持久化存储

    http://blog.csdn.net/yinwenjie/article/details/53518286 Redis从2.X版本开始,就支持一种基于非持久化消息的.使用发布/订阅模式实现的事件通 ...

  6. redis事件监听及在订单系统中的使用

    https://blog.csdn.net/qq_37334135/article/details/77717248 通常在网上买好物品,或者说手机扫码后,点击付款,这时就会向后台发送请求,生成订单信 ...

  7. Redis事件库源码分析

    由于老大在新项目中使用redis的事件库代替了libevent,我也趁着机会读了一遍redis的事件库代码,第一次读到“优美,让人愉快”的代码,加之用xmind制作的类图非常帅,所以留文纪念. Red ...

  8. Redis事件通知示例

    1. redis如同zk一样,提供了事件监听(或者说是回调机制), 下面是redis的配置说明: ############################# EVENT NOTIFICATION ## ...

  9. Redis事件机制

    Redis服务器是一个事件驱动程序,服务器需要处理以下两类事件: 文件事件:Redis通过套接字与客户端连接,文件事件是服务器对套接字操作的抽象. 时间事件:Redis服务器中的一些操作需要给定的时间 ...

随机推荐

  1. 连接Oracle 10g时ORA-12514:TNS:监听进程不能解析在连接描述符中给出的SERVICE_NAME错误的解决

    近日服务器断电,导致客户端连接ORACLE服务器时出现ORA-12514错误,在网上查得解决方法如下 解决方法: 1. 打开/network/admin/listener.ora文件,找到: SID_ ...

  2. 第1章 HTML基础

    1.1 HTML概述 1.1.1 什么是HTML HTML(Hyper Text Markup Language,超 文本 标记 语言)是纯文本类型的语言,它是Internet上用于编写网页的主要语言 ...

  3. day05_09 列表内置方法

    1.0 count(计算元素出现的次数) t = ['to','be','or','not','to','be'].count('to') print(t) #>>>2 2.0 ex ...

  4. 数据结构设计 Stack Queue

    之前在简书上初步总结过几个有关栈和队列的数据结构设计的题目.http://www.jianshu.com/p/d43f93661631 1.线性数据结构 Array Stack Queue Hash ...

  5. Leetcode 617.合并二叉树

    合并二叉树 给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠. 你需要将他们合并为一个新的二叉树.合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新 ...

  6. Android版本对应的API号

    Android版本 API 级别 1.5 API 3 1.6 API 4 2.1 API 7 2.2 API 8 2.3.3 API 10 3.0 API 11 3.1 API 12 3.2 API ...

  7. 【转】netstat 查看端口占用情况

    netstat用来查看系统当前系统网络状态信息,包括端口,连接情况等,常用方式如下: netstat -atunlp,各参数含义如下: -t : 指明显示TCP端口 -u : 指明显示UDP端口 -l ...

  8. 个人环境搭建——搭建jenkins持续构建集成环境

    ---恢复内容开始--- 搭建jenkins持续构建集成环境  要搭建jenkins持续构建集成环境,首先要安装tomcat和JDK:   第一部分,基本说明:   敏捷(Agile) 在软件工程领域 ...

  9. [暑假集训--数论]poj1595 Prime Cuts

    A prime number is a counting number (1, 2, 3, ...) that is evenly divisible only by 1 and itself. In ...

  10. bzoj 4310 跳蚤 二分答案+后缀数组/后缀树

    题目大意 给定\(k\)和长度\(\le10^5\)的串S 把串分成不超过\(k\)个子串,然后对于每个子串\(s\),他会从\(s\)的所有子串中选择字典序最大的那一个,并在选出来的\(k\)个子串 ...