深入解析Redis中的事件

redis的事件模型详解(结合Reactor设计模式)         文章基于redis-4.0.1源码详细介绍一下redis的事件模型。       一、redis事件模型概览         redis是一个事件驱动的服务程序,在redis的服务程序中存在两种类型的事件,分别是文件事件和时间事件。文件事件是对网络通信操作的统称,时间事件是redis中定时运行的任务或者是周期性的任务(目前redis中只有serverCron这一个周期性时间事件... 阅读详情
Redis服务器是一个事件驱动程序,服务器需要处理以下两类事件:                                                                                          	□文件事件:Redis服务器通过套接字与客户端进行连接,而文件事件就是服务器对套接字操作的抽象。服务器与客户端的通信会产生相应的文件事件,而服务器则通过监听并处理这些事件来完成一系列网络通信操作。                                                                                                                                                                                                         	□ 时间事件:服务器的一些操作需要在给定的时间点执行,而时间事件就是对这类定时操作的抽象。

1.文件事件

Redis棘突Reactor模式开发了自己的网络事件处理器:这个处理器被称为文件事件处理器:                                              	□文件事件处理器使用IO多路复用程序来同时监听多个套接字,并根据套接字目前执行的任务来为套接字关联不同的事件处理器。                                                                                                                                                                   	□ 当被监听的套接字准备好执行连接应答、读取、写入、关闭等操作时,与操作相对应的文件事件就会产生,这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。

虽然文件事件处理器以单线程方式运行,但通过使用IO多路复用程序来监听多个套接字,文件事件处理器既实现了高性能的网络通信模型,又可以很好地与服务器中其他同样以单线程方式运行的模块进行对接,这保持了Redis内部单线程设计的简单性。
  1. 文件事件处理器的构成:

    1、文件事件是对套接字操作的抽象,因为一个服务器会连接多个套接字,所以多个文件事件有可能会并发地出现。 IO多路复用程序负责监听多个套接字,并向文件事件分派器传送那些产生了事件的套接字。
    2、尽管多个文件事件可能会并发地出现,但IO多路复用程序总是会将所有产生事件的套接字都放到一个队列里,然后通过这个队列,以有序、同步、每次一个套接字的方式向文件事件分派器传送套接字。当上一个套接字产生的事件被处理完毕后,才会继续向文件事件分派器传送下一个套接字。
    3、文件事件分派器接收IO多路复用程序传来的套接字,并根据产生的事件的类型,调用相应的事件处理器。 服务器会为执行不同任务的套接字关联不同的事件处理器,这些处理器是一个个函数,它们定义了某个事件发生时,服务器应该执行的操作。

  2. IO多路复用程序的实现:
    1、Redis的IO多路复用程序的所有功能都是通过包装常见的select、epoll、evport和kqueue这些IO多路复用函数库来实现的,每个函数库在Redis源码中都对应一个单独的文件。因为Redis为每个IO多路复用函数库都实现了相同的API,所以底层实现是可以互换的。
    2、Redis在IO多路复用程序的实现源码中用#include宏定义相应的规则,程序会在编译时自动选择系统中性能最高的IO多路复用函数库来作为Redis的底层实现。

  3. 事件的类型:
    1、IO多路复用程序可以监听多个套接字的READABLE和WRITABLE事件,这2类事件和套接字操作之间的对应关系如下:
    当套接字变得可读时(客户端对套接字执行write操作或close操作),或者有新的可应答套接字出现时(客户端对服务器的监听套接字执行connect操作),套接字产生AE_READABLE事件。
    当套接字变得可写时(客户端对套接字执行read操作),套接字产生AE_WRITAVLE事件。
    2、IO多路复用程序允许服务器同时监听套接字的可读可写事件,如果一个套接字同时产生了这两种事件,那么文件事件分派器会优先处理AE_READABLE事件。即先读后写。

  4. 文件事件的处理器:
    1、连接应答处理器:
    acceptTcpHandler函数是连接应答处理器,用于对连接服务器监听套接字的客户端进行应答。
    当服务器进行初始化时,程序会将这个连接应答处理器和服务器监听套接字的AE_READABLE事件关联起来,当有connect函数连接服务器监听套接字的时候,套接字就会产生READABLE事件,引发连接应答处理器执行,并执行相应的套接字应答操作。
    2、命令请求处理器:
    readQueryFromClient函数是Redis的命令请求处理器,这个处理器负责从套接字中读入客户端发送的命令请求内容。
    当一个客户端通过连接应答处理器成功连接到服务器后,服务器会将客户端套接字的READABLE事件和命令请求处理器关联起来,当客户端向服务器发送请求时,套接字就会产生READABLE事件,引发命令请求处理器执行,并执行相应的套接字读入操作。
    3、命令回复处理器:
    sendReplyToClient函数是Redis的命令回复处理器,负责将服务器执行命令后得到的命令回复通过套接字返回给客户端。
    当服务器有命令回复需要传送给客户端的时候,服务器会将WRITABLE事件和命令回复处理器关联器关联起来,当客户端准备好接收服务器传回的命令回复时,就会产生WRITABLE事件,引发命令回复处理器执行,并执行相应的套接字写入操作。

2.时间事件

Redis的时间事件分为以下两类:定时事件:让一段程序在指定的时间之后执行一次。周期性事件:让一段程序每隔指定时间就执行一次。

一个时间事件主要由以下3个属性组成:id:服务器为时间事件创建的全局唯一ID。ID号按从小到大的顺序递增,新事件的ID号比旧事件的ID号要大。when:毫秒精度的UNIX时间戳,记录了时间事件的到达时间。 timeProc:时间事件处理器,一个函数,当时间事件到达时,服务器就会调用相应的处理器来处理事件。           一个事件时定时事件还是周期性事件取决于时间事件处理器的返回值。

如果事件处理器返回NOMORE,那么这个事件为定时事件:该事件在达到一次后就会被删除。

如果事件处理器返回一个非NOMORE的整数值,那么这个事件为周期性事件。当一个时间事件到达后,服务器会根据事件处理器返回的值,对时间事件的when属性进行更新,让这个事件在一段时间后再次到达,并以这种方式一直更新并运行下去。 目前版本Redis只使用周期性事件,而没有定时事件。
  1. 实现:
    1、服务器将所有时间事件都放在一个无序链表中,每当时间事件执行器运行时,它就遍历整个链表,查找所有已到达的时间事件,并调用相应的事件处理器。
    2、保存时间事件的链表为无序链表,指的不是链表不按ID排序,而是说,该链表不按when属性的大小排序。正因为链表没有按when属性进行排序,所以当时间事件执行器运行的时候,它必须遍历链表中的所有,才能确保服务器中所有已到达的时间事件都会被处理。
    3.无序链表并不影响时间事件处理器的性能,正常模式下只使用serverCron一个时间事件。
  2. 时间事件应用实例:serverCron函数
    1、持续运行的Redis服务器需要定期对自身的资源和状态进行检查和调整,从而确保服务器可以长期、稳定地运行,这些定期操作由serverCron函数负责执行,它的工作包括:
    □更新服务器的各类统计信息,比如时间、内存占用、数据库占用情况等。
    □清理数据库中的过期键值对。
    □关闭和清理连接失效的客户端。
    □尝试进行AOF和RDB持久化操作。
    □如果服务器是主服务器,那么对从服务器进行定期同步。
    □如果处于集群模式,对集群进行定期同步和连接测试。

3.事件的调度与执行

事件的调度和执行由aeProcessEvents函数负责。
  1. 以下是事件的调度和执行规则:
    1、aeApiPoll函数的最大阻塞时间由到达时间最接近当前时间的时间事件决定,这个方法既可以避免服务器对时间事件进行频繁的轮询,也可以确保不会阻塞过长时间。
    2、因为文件事件时随机出现的,如果等待并处理完一次文件事件后,仍未有任何时间事件到达,那么服务器将再次等待并处理文件事件。随着文件事件的不断执行,时间会逐渐向时间事件所设置的到达时间逼近,并最终来到到达时间。这时服务器就可以开始处理到达的时间事件了。
    3、对文件事件和时间事件的处理都是同步、有序、原子执行的,服务器不会中途中断事件处理,也不会对事件进行抢占。因此,它们都会尽可能减少程序的阻塞时间,并在有需要时主动让出执行权,从而降低饥饿的可能性。
    4、因为时间事件在文件事件之后执行,并且事件之间不会出现抢占,所以时间事件的实际处理事件,通常会比设定的到达时间稍晚一些。

4.重点回顾

  1. Redis服务器时一个事件驱动程序,服务器处理的事件分为时间事件和文件事件两类。
  2. 文件事件处理器是基于Reactor模式实现的网络通信程序。
  3. 文件事件时对套接字操作的抽象:每次套接字变为可应答、可写或可读时,相应的文件产生
  4. 文件事件分为AE_READABLE和AE_WEITABLE事件两类。
  5. 时间事件分为定时事件和周期性事件:定时事件只在指定的时间到达一次,而周期性事件则每隔一段时间到达一次。
  6. 服务器在一般情况下只执行serverCron函数一个时间事件,并且这个事件时周期性事件。
  7. 文件事件和时间事件之间是合作关系,服务器会轮流处理这两种事件,并且过程中也不会进行抢占
  8. 时间事件的实际处理过程通常会比设定的到达时间晚一些。
Redis 源码硬核解析系列专题 - 第五篇:事件驱动模型与网络层 收获:理解Redis事件驱动与网络层实现。调试技巧:用strace跟踪epoll_wait调用,或用gdb打印。下一步:探索内存管理和持久化。 阅读详情

相关推荐

Redis事件处理与客户端连接管理深入解析

本文深入探讨了Redis中事件循环的工作机制以及如何管理客户端连接。详细分析了Redis如何通过全局对象aeEventLoop中的events和fired数组定位到对应的client对象,以及在读写事件发生时如何触发相应的回调函数。此外,还涉及了客户端断开流程的处理逻辑。

weixin_35649491的博客 363

【redis原理】redis事件机制

redis事件机制分析,涉及文件事件和时间事件,主要涉及源码分析

dylan的博客 846

12V转5V稳压电路详细分析(7805三端稳压,LM2596稳压)

7805线性三端稳压 DCDC的意思是直流变到直流(不同直流电源值的转换),只要符合这个定义都可以叫DCDC转换器,或称之为开关电源或开关调整器。 7805属于常用的线性三端稳压器,输入电压范围不大于35V,输入输出压差2V,最大输出电流1.5A,下图为原理图,其原理简单,使 用方便,深受很多用户的喜爱。但是其不足之处就是效率低,特别是压差越大时其效率越低。比如这里12V转5V的效率为 5V/12V≈41.7%。 如上电路是最经典的7805稳压5V电路,电路中有两个电容,电容的作用如下: ...

a2001444的博客 9万+

redis的事件机制

转自:http://www.hoterran.info/redis_eventlibrary   相当清晰 每个cs程序尤其是高并发的网络服务端程序都有自己的网络异步事件处理库,redis不例外。事件库仅仅包括ae.c、ae.h,还有3个不同的多路复用(本文仅描述epoll)的wrapper文件,事件库封装了框架调用的主循环函数,暴露了时间、文件事件注册和销毁函数,典型的依赖反转模

momo 1815

GX Works2系统启动失败排查指南:从环境配置到修复方案

在工业自动化与PLC编程调试中,软件启动异常是常见的工程痛点。当开发工具因系统环境配置不当而频繁报错时,往往不是简单的重启能解决的。运行库缺失、区域设置错误、临时目录失效或系统服务被禁用,都可能导致编程软件无法完成初始化流程。掌握从基础环境检查到系统组件修复的系统性排查思路,是提升工控开发效率的关键能力。本文从软件初始化原理出发,结合Windows系统维护实践,梳理一套适用于工业软件启动故障的通用诊断方法,并自然聚焦到三菱GX Works2常见启动失败问题的实际处理,帮助工程师快速定位并解决环境性故障,保障

weixin_42567046的博客 448

Autowired的使用介绍

我们都知道在spring中@Autowired注解,是用来自动装配对象的。@Service@Autowired没错,这样是能够装配成功的,因为默认情况下spring是按照类型装配的,也就是我们所说的byType方式。此外,@Autowired注解的required。

白话机器学习 1349

redis详解

工作原理 事件模型 redis以其高性能而闻名,它最大程度地利用了 单线程,非阻塞,多路复用的I/O模型 来快速地处理请求。 通信协议 Redis基本上就是一个接受并处理来自客户端请求的非阻塞、I/O复用的TCP服务器。我们可以使用各种编程语言通过TCP协议与Redis进行通信。对Redis来说,这种通信协议叫做Redis Serialization Protocal(RESP,Redis序列...

YABAJ的专栏 1941

翁恺-C语言程序设计 PTA习题集

代码练习题

qq_46085472的博客 7639

redis入门(二):redis的命令集合

redis 中根据不同的数据结构,分为了不同的api操作。有String 操作,Hash 操作,List 操作,Set 操作,不同的数据结构有着不同的数据实现形式在api的表现也是不同的。 redis的所有命令api在 官网 已经全部展示出来,而redis-py 的基本上都已经实现了上面所有的命令,除了特殊几个以外:SELECT,DEL,MULTI/EXEC,SUBSCRIBE/LISTEN``SCAN/SSCAN/HSCAN/ZSCAN。 下面是几个数据结构常用的命令: String 操作 set()

haleycat的博客 1376

Joern实战:从代码导入到Python分析的全流程避坑指南(附常见错误解决方案)

本文详细介绍了Joern静态分析工具从代码导入到Python分析的全流程实践指南,包括环境配置、代码导入技巧、数据库服务优化、Python交互分析及性能调优等关键步骤。特别针对常见错误提供了实用解决方案,帮助开发者高效进行代码安全分析和漏洞挖掘。

weixin_28309571的博客 138

点云语义分割:PointNet训练S3DIS数据集

文章目录一、数据准备1.1、数据下载二、训练三、测试 项目地址:pointnet 此次我们是用pointnet网络来做语义分割。代码在pointnet项目中的sem_seg文件夹下,里面也有README.md介绍了训练的过程。 一、数据准备 1.1、数据下载 原始数据下载 处理好的h5格式数据下载 二、训练 三、测试 ...

zhaoguanhua的博客 4176

redis事件类型解析

redis服务器是一个事件驱动程序,服务器总体来说可以分为两种事件:文件事件和时间事件,下面根据这两种事件分别进行介绍 文件事件 上图: 可以看到,文件事件处理器由四部分组成:分别是套接字,io多路复用程序,多路复用分派器和各种不同的事件处理器组成。 套接字 可以理解为不同的客户端请求 io多路复用程序 redis统一封装了常见的io多路复用函数,譬如select,epoll,evport,和kqueue,并且提供了相同的api(多态?策略设计模式?),导致redis程序会在编译时候自动选择系统中性能最

weixin_40421175的博客 282

200、从反激到LLC:工程师的成长之路

文章摘要: 本文以工程师视角探讨从反激式到LLC电源设计的思维转变。通过48V通信电源故障案例,揭示LLC谐振电容ESR温度特性引发的隐患,强调LLC需精确计算与测试。对比反激与LLC的核心差异:反激需控制寄生参数(如漏感尖峰、电容ESR),而LLC的关键在于频率响应和死区时间优化。作者提出三大思维转变:从匝比计算转向增益曲线分析,从时域波形观察转向频域频谱诊断,从元件更换转向参数调整。最后给出实战建议,包括建立故障库、关注元件参数细节及示波器调试技巧,指出工程师需从"控制"思维升级为"谐振"思维,实现技术

Jack010169的博客 321

Redis源码解析:事件驱动框架

介绍 为了高效的处理网络请求,演化出了Reactor模型。 Reactor模型主要有reactor,acceptor,handler三种角色 reactor:分配事件 acceptor:建立连接 handler:处理请求 单Reactor单线程 accept->read->处理业务逻辑->write 在一个线程 单Reactor多线程 accept,read,write复用一个线程 处理请求用一个工作线程池 主从Reactor多线程 accpet复用一个线程 read write复用

小识的博客 4051

Autosar软件组件分析及ARXML文件分析

Autosar软件组件分析及ARXML文件分析

专注汽车软件开发、AutoSAR、车载以太网、SOA、EE架构。 3600

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Redis时间事件源码解析

Redis的时间事件分为两类:1、定时事件:让一段程序在指定的时间之后执行一次。2、周期性事件:让一段程序每隔指定的时间就执行一次。(比如serverCron函数,每秒执行次数通过redis.conf/hz设置)目前版本的Redis只使用周期性事件,而没有使用定时事件。具体源码参考ae.c/ae.h文件中。文中的源码注释参考于黄建宏。在介绍时间事件结构之前,先看表征事件处理器的状态的结构:type...

qq_35181209的博客 1451

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

redis0.1源码解析之事件驱动

redis的事件驱动模块负责处理文件和定时器两种任务。 下面是几个函数指针 typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask); typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData); typedef void aeEventFinalizerProc(struc

标子 的专栏 328

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Redis源代码解析:13Redis中的事件驱动机制

         Redis中。处理网络IO时,採用的是事件驱动机制。但它没有使用libevent或者libev这种库,而是自己实现了一个很easy明了的事件驱动库ae_event,主要代码只400行左右。          没有选择libevent或libev的原因大概在于。这些库为了迎合通用性造成代码庞大,并且当中的非常多功能,比方监控子进程,复杂的定时器等。这些都不是Redis所须...

weixin_34232617的博客 115

Redis 源码解析 - Redis 事件处理实现

Redis 事件处理的核心机制是基于 I/O 多路复用技术实现的,具体来说,它采用了 epoll(Linux 平台)或其他类似的系统调用(如 kqueue、select 等)。在 Redis 源码中,事件处理器的设计体现了高并发场景下的高效网络通信模型,同时也保持了 Redis 内部的单线程架构简单性。总结起来,Redis 的事件处理机制确保了即使在单线程环境下也能高效处理大量并发连接,这是因为通过 I/O 多路复用技术,Redis 可以在一个线程内同时监听并处理多个连接的读写需求,而非阻塞等待单一连接。

qq_33240556的博客 313

终极指南:Node.js事件循环与Redis无缝集成——node-redis事件机制深度解析

在现代Node.js应用开发中,高效处理I/O操作是提升性能的关键。作为最流行的Node.js Redis客户端,node-redis通过精妙的事件机制与Node.js事件循环深度协同,实现了非阻塞的Redis数据交互。本文将带你全面了解node-redis如何利用事件驱动架构优化性能,以及如何在实际项目中避免常见的事件循环阻塞问题。 ## 为什么Node.js事件循环对Redis集成至关重要?

gitblog_00619的博客 476

redis源码解析之事件驱动

redis源码解析之事件驱动 Redis 内部有个小型的事件驱动,它主要处理两项任务: 文件事件:使用I/O多路复用技术处理多个客户端请求,并返回执行结果。 时间事件:维护服务器的资源管理,状态检查。 主要的数据结构包括文件事件结构体,时间事件结构体,触发事件结构体,事件循环结构体 /* File event struc...

weixin_30600197的博客 167

第28章—内核解析篇:Redis事件驱动核心框架解析

在这一节中,我们重点介绍了 Redis 事件驱动框架(ae 库)的核心实现。首先,我们深入分析了 ae 库的设计理念;然后以 Linux 平台为例,分析了 aeApiState 结构体的实现;接下来分析了 Redis 中对网络事件()以及时间事件()的抽象,以及处理事件的抽象 —— aeEventLoop 结构体;最后,我们深入剖析了 aeEventLoop 初始化、注册监听以及处理事件的核心逻辑。

运维老生常谈 754

Redis/hiredis异步客户端与GLib事件循环集成解析

Redis作为高性能的内存数据库,其客户端库hiredis提供了多种编程接口。本文将深入分析hiredis如何与GLib事件循环集成,实现异步非阻塞的Redis操作模式。这种集成方式特别适合基于GTK+或GLib的应用程序开发。 ## 核心组件分析 ### 1. 异步连接管理 示例代码展示了如何建立异步Redis连接: ```c ac = redisAsyncConnect("127.0....

gitblog_00140的博客 530

Redisson实现Redis数据库刷新事件监听机制解析

Redis作为高性能的内存数据库,在实际应用中经常需要处理数据刷新的场景。Redisson作为Redis的Java客户端,提供了强大的功能扩展。本文将深入分析Redisson如何实现对Redis FLUSHALL/FLUSHDB操作的监听机制。 ## 背景与需求 在分布式系统中,当Redis执行FLUSHALL或FLUSHDB命令时,客户端需要及时感知这一变化。传统方案是通过Redis的键空间...

gitblog_00276的博客 353

Redis源码解析:13Redis中的事件驱动机制

Redis中,处理网络IO时,采用的是事件驱动机制。但它没有使用libevent或者libev这样的库,而是自己实现了一个非常简单明了的事件驱动库ae_event,主要代码仅仅400行左右。          没有选择libevent或libev的原因大概在于,这些库为了迎合通用性造成代码庞大,而且其中的很多功能,比如监控子进程,复杂的定时器等,这些都不是Redis所需要的。

程序员的自我修养 3212
上一篇: 深入解析Redis的AOF持久化
下一篇: 剖析Redis客户端
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值