返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >Redis定时任务原理的实现
  • 784
分享到

Redis定时任务原理的实现

2024-04-02 19:04:59 784人浏览 泡泡鱼
摘要

目录数据结构常见操作1. 创建定时事件2. 触发定时事件3. 执行定时事件总结本文主要是基于 Redis 6.2 源码进行分析定时事件的数据结构和常见操作。 数据结构 在 redis

本文主要是基于 Redis 6.2 源码进行分析定时事件的数据结构和常见操作。

数据结构

在 redis 中通过 aeTimeEvent 结构来创建定时任务事件,代码如下:


typedef struct aeTimeEvent {
    // 标识符
    long long id; 
    // 定时纳秒数
    monotime when;
    // 定时回调函数
    aeTimeProc *timeProc;
    // 注销定时器时候的回调函数
    aeEventFinalizerProc *finalizerProc;
    void *clientData;
    struct aeTimeEvent *prev;
    struct aeTimeEvent *next;
    int refcount; 
} aeTimeEvent;

常见操作

1. 创建定时事件

redis 中最重要的定时函数且是周期执行的函数,使用的是 serverCron 函数。在 redis 中由于定时任务比较少,因此并没有严格的按照过期时间来排序的,而是按照 id自增 + 头插法 来保证基本有序。

if (aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL) == AE_ERR) {
  serverPanic("Can't create event loop timers.");
  exit(1);
}

//创建定时器对象
long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
        aeTimeProc *proc, void *clientData,
        aeEventFinalizerProc *finalizerProc)
{
    long long id = eventLoop->timeEventNextId++;
    aeTimeEvent *te;

    te = zmalloc(sizeof(*te));
    if (te == NULL) return AE_ERR;
    te->id = id;
    te->when = getMonotonicUs() + milliseconds * 1000;
    te->timeProc = proc;
    te->finalizerProc = finalizerProc;
    te->clientData = clientData;
    te->prev = NULL;
    // 头插法 
    te->next = eventLoop->timeEventHead;
    te->refcount = 0;
    if (te->next)
        te->next->prev = te;
    eventLoop->timeEventHead = te;
    return id;
}

2. 触发定时事件

redis 中是采用 io 复用来进行定时任务的。

查找距离现在最近的定时事件,见 usUntilEarliestTimer

​

static int64_t usUntilEarliestTimer(aeEventLoop *eventLoop) {
    aeTimeEvent *te = eventLoop->timeEventHead;
    if (te == NULL) return -1;

    aeTimeEvent *earliest = NULL;
    while (te) {
        if (!earliest || te->when < earliest->when)
            earliest = te;
        te = te->next;
    }

    monotime now = getMonotonicUs();
    return (now >= earliest->when) ? 0 : earliest->when - now;
}

​

这里时间复杂度可能比较高,实际中需要结合具体场景使用。

更新剩余过期时间,想想为啥呢?因为我们前面提到过,IO 复用有可能因为 IO 事件返回,所以需要更新。

if (flags & AE_TIME_EVENTS && !(flags & AE_DONT_WaiT))
  usUntilTimer = usUntilEarliestTimer(eventLoop);

if (usUntilTimer >= 0) {
  tv.tv_sec = usUntilTimer / 1000000;
  tv.tv_usec = usUntilTimer % 1000000;
  tvp = &tv;
} else {
  if (flags & AE_DONT_WAIT) {
    // 不等待
    tv.tv_sec = tv.tv_usec = 0;
    tvp = &tv;
  } else {
    
    tvp = NULL; 
  }
}

3. 执行定时事件

一次性的执行完直接删除,周期性的执行完在重新添加到链表


static int processTimeEvents(aeEventLoop *eventLoop) {
  int processed = 0;
  aeTimeEvent *te;
  long long maxId;

  te = eventLoop->timeEventHead;
  maxId = eventLoop->timeEventNextId-1;
  monotime now = getMonotonicUs();
  
  // 删除定时器
  while(te) {
    long long id;
        
    // 下一轮中对事件进行删除
    
    if (te->id == AE_DELETED_EVENT_ID) {
      aeTimeEvent *next = te->next;
      
      if (te->refcount) {
        te = next;
        continue;
      }
      if (te->prev)
        te->prev->next = te->next;
      else
        eventLoop->timeEventHead = te->next;
      if (te->next)
        te->next->prev = te->prev;
      if (te->finalizerProc) {
        te->finalizerProc(eventLoop, te->clientData);
        now = getMonotonicUs();
      }
      zfree(te);
      te = next;
      continue;
    }
    
    if (te->id > maxId) {
      te = te->next;
      continue;
    }

    if (te->when <= now) {
      int retval;

      id = te->id;
      te->refcount++;
      // timeProc 函数返回值 retVal 为时间事件执行的间隔
      retval = te->timeProc(eventLoop, id, te->clientData);
      te->refcount--;
      processed++;
      now = getMonotonicUs();
      if (retval != AE_NOMORE) {
        te->when = now + retval * 1000;
      } else {
        // 如果超时了,那么标记为删除
        te->id = AE_DELETED_EVENT_ID;
      }
    }
    // 执行下一个
    te = te->next;
  }
  return processed;
}

总结

优点:实现简单
缺点:如果定时任务很多,效率比较低。

到此这篇关于Redis定时任务原理的实现的文章就介绍到这了,更多相关Redis定时任务内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Redis定时任务原理的实现

本文链接: https://lsjlt.com/news/141506.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Redis定时任务原理的实现
    目录数据结构常见操作1. 创建定时事件2. 触发定时事件3. 执行定时事件总结本文主要是基于 redis 6.2 源码进行分析定时事件的数据结构和常见操作。 数据结构 在 redis...
    99+
    2024-04-02
  • redis如何实现定时任务
    这篇文章将为大家详细讲解有关redis如何实现定时任务,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。技术栈redis / nodeJs / koa技术重难点开启redis...
    99+
    2024-04-02
  • Java定时任务的实现原理是什么
    Java定时任务的实现原理是基于线程池和计时器的机制。在Java中,可以使用ScheduledExecutorService接口来创...
    99+
    2023-10-20
    Java
  • php redis怎么实现定时任务
    本教程操作环境:windows7系统、PHP8.1版、Dell G3电脑。php redis怎么实现定时任务?php + redis 实现定时任务修改配置文件 redis.conf; notify-keyspace-events "...
    99+
    2024-04-02
  • php redis如何实现定时任务
    这篇文章主要介绍“php redis如何实现定时任务”,在日常操作中,相信很多人在php redis如何实现定时任务问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”php redis如何实现定时任务”的疑惑有所...
    99+
    2023-07-04
  • redis如何实现分布式定时任务
    Redis本身并不直接支持分布式定时任务的功能,但可以通过Redis的一些特性和与其他组件的结合来实现分布式定时任务。一种常见的实现...
    99+
    2023-09-06
    redis
  • Java定时任务原理详解
    目录序章一、Scheduled1.1 使用方法1.2 源码分析二、QUARTZ2.1 使用方法2.2 源码分析序章 定时任务实现方式 当下,java编码过程中,实现定时任务的方式主要...
    99+
    2024-04-02
  • JavaScript实现手写原生任务定时器
    功能介绍 定时器顾名思义就是在某个特定的时间去执行一些任务,现代的应用程序早已不是以前的那些由简单的增删改查拼凑而成的程序了,高复杂性早已是标配,而任务的定时调度与执行也是对程序的基...
    99+
    2024-04-02
  • Python实现定时任务
    Python下实现定时任务的方式有很多种方式。下面介绍几种 循环sleep: 这是一种最简单的方式,在循环里放入要执行的任务,然后sleep一段时间再执行。缺点是,不容易控制,而且sleep是个阻塞函数。...
    99+
    2022-06-04
    Python
  • Java实现定时任务
    本文实例为大家分享了Java实现定时任务的具体代码,供大家参考,具体内容如下 1 使用java.util.Timer 这种方式的定时任务主要用到两个类,Timer 和 TimerTa...
    99+
    2024-04-02
  • PHP中使用Redis实现分布式定时任务
    Redis是一种高性能的内存数据库,它具有快速的读写速度、支持一定级别的持久性和丰富的数据类型等优点。Redis常被用于缓存、消息队列、实时排行榜等场景。在开发中,我们有时会需要实现分布式的定时任务,比如:发送邮件、清理临时文件、更新缓存等...
    99+
    2023-05-15
    分布式 PHP redis
  • 如何利用Redis实现分布式定时任务
    Redis是一个出色的键值存储系统,除了作为缓存使用,还有许多其他用途。其中之一便是作为分布式定时任务的实现工具。在本文中,我们将介绍如何利用Redis实现分布式定时任务,同时提供相应的代码示例。什么是分布式定时任务?在单机环境中,我们可以...
    99+
    2023-11-07
    分布式 redis 定时任务
  • 怎么深入Java Timer 定时任务调度器实现原理
    这篇文章将为大家详细讲解有关怎么深入Java Timer 定时任务调度器实现原理,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。使用 Java 来调度定时任务时,我们经常会使用 Timer 类...
    99+
    2023-06-02
  • PHP中使用Redis实现限时任务处理
    随着互联网和移动互联网的发展,越来越多的应用需要进行后台任务处理。这些任务可能包括发送电子邮件、统计数据、生成报告等。在PHP中,通常使用CRON定时任务或者队列任务来实现后台任务处理。但是,在某些情况下,可能需要对任务进行限时处理,以避免...
    99+
    2023-05-16
    PHP redis 限时任务处理
  • python-crontab实现定时任务
    用django-crontab实现定时任务: 1.安装django-crontab 2.安装完成后,将‘django-crontab’添加到settings.py中的INSTALL_APP中, 然后在CRONJOBS中定义自己的定时任务 ...
    99+
    2023-01-31
    python crontab
  • JavaScript如何实现手写原生任务定时器
    这篇文章主要介绍JavaScript如何实现手写原生任务定时器,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!功能介绍定时器顾名思义就是在某个特定的时间去执行一些任务,现代的应用程序早已不是以前的那些由简单的增删改查拼...
    99+
    2023-06-29
  • Python中threading.Timer()定时器实现定时任务
    目录1、单线程执行2、多线程执行timer最基本理解就是定时器,可以启动多个定时任务,这些定时器任务是异步执行,所以不存在等待顺序执行问题。 Timer方法说明Timer(inter...
    99+
    2023-01-28
    threading.Timer()定时器 threading.Timer()定时任务
  • mysql实现定时任务的方法
    自MySQL5.1.6起,增加了一个非常有特色的功能-事件调度器(Event Scheduler),可以用做定时执行某些特定任务(例如:删除记录、对数据进行汇总、数据备份等等),来取代原先只能由操作系统的计...
    99+
    2024-04-02
  • SpringTask定时任务的实现详解
    目录Spring Task定时任务Cron表达式实现定时任务背景实现Spring Task定时任务 Cron表达式 以6-7位的一组数字,中间用空格间隔的字符串,表达一种时间 每位的...
    99+
    2022-11-13
    Spring Task定时任务 Spring定时任务
  • python怎么实现定时任务
    这篇文章主要介绍python怎么实现定时任务,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!用Python实现定时任务有些时候我们需要每隔一段时间就要执行一段程序,或者是往复循环执行某一个任务。比如博主在上篇文章讲的爬...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作