[redis 源码走读] 事件 - 定时器

本文详细探讨了Redis定时器的功能及其实现原理,包括定时器的作用、实现机制、单进程异步事件处理逻辑、多定时任务处理以及定时器执行频率控制。通过分析,读者将了解到Redis如何高效管理时间事件,处理过期数据回收、持久化快照、链接回收等关键任务。

定时器是 redis 异步处理事件的一个十分重要的功能。redis 定时器功能由多个时间事件组成,事件由一个双向链表维护。时间事件可以处理多个定时任务。


理解 redis 定时器,我们带着问题,看看 redis 是怎么处理的:

  • 定时器作用是什么。
  • 定时器实现原理。
  • 单进程里如何同时处理文件事件和时间事件。
  • 如何实现多定时任务。

🔥文章来源:wenfh2020.com

1. 作用

定时器是 redis 异步处理任务的一个十分重要的功能。核心逻辑在 serverCron 函数里。

  • 对设置了过期时间的数据进行检查回收。
  • 异步回收需要关闭的链接(socket)。
  • 检查 fork 的子进程是否已经关闭,处理回收的相关工作。
  • 检查内存数据是否符合 rdb 持久化快照落地条件,fork 子进程进行快照保存。
  • bgsave rdb 生成快照或 bgrewriteaof aof 重写延后操作。
  • 对需要扩容和缩容的哈希表(dict)进行数据迁移。
  • 集群里节点间的断线重连。
  • redis 服务的一些信息统计。
  • …等等。

2. 定时器实现原理

redis 定时器功能由多个时间事件组成,事件由一个双向链表维护。有些实现逻辑,上文已经提到,下面就简单说一下部分实现原理。


2.1. 事件结构

  • 事件。
// 时间事件
typedef struct aeTimeEvent {
   
   
    long long id; /* time event identifier. */
    long when_sec; /* seconds */
    long when_ms; /* milliseconds */
    aeTimeProc *timeProc; /* 时钟到期事件触发回调处理函数。*/
    aeEventFinalizerProc *finalizerProc; /* 时间事件删除时,触发回调。*/
    void *clientData; /* 扩展参数,异步操作方便数据回调,在 timeProc 通过参数回传。*/
    struct aeTimeEvent *prev; /* 时间事件是一个双向链表。*/
    struct aeTimeEvent *next;
} aeTimeEvent;

// 事件管理
typedef struct aeEventLoop {
   
   
    ...
    long long timeEventNextId;  // 时间事件下一个 id (通过 ‘++’ 递增)
    ...
    aeTimeEvent *timeEventHead; // 时间事件链表。
    ...
} aeEventLoop;
  • 事件循环。
// 循环处理事件。
void aeMain(aeEventLoop *eventLoop) {
   
   
    eventLoop->stop = 0;
    while (!eventLoop->stop) {
   
   
        if (eventLoop->beforesleep != NULL)
            eventLoop->beforesleep(eventLoop);
        aeProcessEvents(eventLoop, AE_ALL_EVENTS|AE_CALL_AFTER_SLEEP);
    }
}
  • 事件回调函数。

// 时间事件触发处理函数。
typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);

// 时间事件处理完毕,被删除时,触发的回调处理。
typedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData);
  • 创建时间事件,时间事件通过双向链表管理,新的事件插入到链表头。
long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
        aeTimeProc *proc, void *clientData,
        aeEventFinalizerProc *finalizerProc) {
   
   
    // 事件 id 递增。
    long long id = eventLoop->timeEventNextId++;
    aeTimeEvent *te;

    te = zmalloc(sizeof(*te));
    if (te == NULL) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值