用redis完成类似 at 命令的功能,例如订单24小时后没有支付自动关闭,定时发邮件,主要说下任务生成之后怎么触发消费。

使用 有序集合

思路: 使用sorted Sets的自动排序, key 为任务id,score 为任务计划执行的时间戳,这样任务在加入sets的时候已经按时间排序,这样每隔1s(或者其他间隔)去取出sets顶部的数据,小于当前时间的可以通过pop取出来然后去执行。

redis模拟
127.0.0.1:6379> zadd cron 10001 task1
(integer) 1
127.0.0.1:6379> zadd cron 9001 task2
(integer) 1
127.0.0.1:6379> zadd cron 29001 task3
(integer) 1
127.0.0.1:6379> ZRANGE cron 0 -1 withscores
1) "task2"
2) "9001"
3) "task1"
4) "10001"
5) "task3"
6) "29001"

假设当前的时间戳是 15000

127.0.0.1:6379> ZRANGEBYSCORE cron -inf 15000
1) "task2"
2) "task1"
127.0.0.1:6379> ZREM cron task2
(integer) 1
127.0.0.1:6379> ZREM cron task1
(integer) 1
127.0.0.1:6379> ZRANGE cron 0 -1 withscores
1) "task3"
2) "29001"

上面的测试直接把小于当前时间戳的所有任务都做了一遍,会有些bug,例如找个定时监测程序挂了2天, 对于某些任务可能有效期只有那么10分钟,重新启动定时监测程序,就会把过期任务也做了一遍, 那么我们选取任务的时候范围要更精确一些。

如果当前时间戳是 29100 可以取到 task3
127.0.0.1:6379> ZRANGEBYSCORE cron 28500 29100
1) "task3"

如果当前时间戳是 30600 就无法取到 task3, 注意对过期任务的清理
127.0.0.1:6379> ZRANGEBYSCORE cron 30000 30600
(empty list or set)

利用键过期通知

思路: reids 2.8 有一种 键空间通知的机制 Keyspace Notifications (强烈推荐看一遍), 允许客户端去订阅一些key的事件,其中就有 key过期的事件,我们可以把 key名称设置为 task的id等标识(这种方式value的值无法取到,所以只用key来识别任务),expire设置为计划要执行的时间,然后开启一个客户端来订阅消息过期事件,然后处理task。

需要更改redis配置,注意版本要在2.8.0以上, 如果没有这个key 请添加上,如果有请更改为下面这样

notify-keyspace-events Ex

重启redis,第一个窗口, 开启订阅

liuzhizhi@lzz-rmbp|redis_test # redis-cli --csv psubscribe '__keyevent@0__:expired'
Reading messages... (press Ctrl-C to quit)
"psubscribe","__keyevent@0__:expired",1
"pmessage","__keyevent@0__:expired","__keyevent@0__:expired","task1"
"pmessage","__keyevent@0__:expired","__keyevent@0__:expired","task2"

第二个窗口 设置key

127.0.0.1:6379> set task1 xx
OK
127.0.0.1:6379> EXPIRE task1 5
(integer) 1
127.0.0.1:6379> set task2 xx
OK
127.0.0.1:6379> EXPIREAT task2 1469525560
(integer) 1

当key过期的时候就看到第一个窗口的通知了,订阅的key __keyevent@<db>__:expired 这个格式是固定的,db代表的是数据库的编号,由于订阅开启之后这个库的所有key过期时间都会被推送过来,所以最好单独使用一个数据库来进行隔离。

小结

以上就是使用redis来处理定时任务的两种思路,常用的编程语言应该都比较容易实现。

[Redis]处理定时任务的2种思路的更多相关文章

  1. PHP实现执行定时任务的几种思路详解

    转:https://segmentfault.com/a/1190000002955509 PHP本身是没有定时功能的,PHP也不能多线程.PHP的定时任务功能必须通过和其他工具结合才能实现,例如Wo ...

  2. 使用Redis实现抢购的一种思路(list队列实现)

    原文:https://my.oschina.net/chinaxy/blog/1829233 抢购是如今很常见的一个应用场景,主要需要解决的问题有两个: 1 高并发对数据库产生的压力 2 竞争状态下如 ...

  3. redis缓存击穿问题一种思路分享

    思路每一个key都有一个附属key1,附属key1可以是key加特定前缀组成,key对应value为真正的缓存数据,附属key1对应的value不重要,可以是随便一个值,附属key1的作用主要是维护缓 ...

  4. js数组去重几种思路

    在一些后台语言中都内置了一些方法来处理数组或集合中重复的数据.但是js中并没有类似的方法,网上已经有一些方法,但是不够详细.部分代码来源于网络.个人总计如下:大致有4种思路 1)使用两次循环比较原始的 ...

  5. CSS实现水平垂直同时居中的5种思路

    × 目录 [1]水平对齐+行高 [2]水平+垂直对齐 [3]margin+垂直对齐[4]absolute[5]flex 前面的话 水平居中和垂直居中已经单独介绍过,本文将介绍水平垂直同时居中的5种思路 ...

  6. CSS实现垂直居中的4种思路

    × 目录 [1]line-height [2]vertical-align [3]absolute [4]flex 前面的话 相对于水平居中,人们对于垂直居中略显为难,大部分原因是vertical-a ...

  7. CSS实现水平居中的4种思路

    × 目录 [1]text-align [2]margin [3]absolute [4]flex 前面的话 水平居中是经常遇到的问题.看似方法较多,条条大路通罗马.但系统梳理下,其实都围绕着几个思路展 ...

  8. 应对Memcached缓存失效,导致高并发查询DB的四种思路(l转)

    当Memcached缓存失效时,容易出现高并发的查询DB,导致DB压力骤然上升. 这篇blog主要是探讨如何在缓存将要失效时,及时地更新缓存,而不是如何在缓存失效之后,如何防止高并发的DB查询. 解决 ...

  9. Spring定时任务的几种实现

    近日项目开发中需要执行一些定时任务,比如需要在每天凌晨时候,分析一次前一天的日志信息,借此机会整理了一下定时任务的几种实现方式,由于项目采用spring框架,所以我都将结合 spring框架来介绍. ...

随机推荐

  1. EntityFramework Core 自动绑定模型映射

    笔者最近在和同事共同开发项目时,需要从他们提供的包含数据库实体类型的类库中读取实体信息绑定到自己的项目中(但是都在同一个解决方案里),所以很直接的一种方式就是把项目中所有的实体都以 public Db ...

  2. AbstractQueuedSynchronizer源码解读--续篇之Condition

    1. 背景 在之前的AbstractQueuedSynchronizer源码解读中,介绍了AQS的基本概念.互斥锁.共享锁.AQS对同步队列状态流转管理.线程阻塞与唤醒等内容.其中并不涉及Condit ...

  3. 【事务】<查询不到同一调用方法其它事务提交的更新>解决方案

    最近遇到一个很棘手的问题,至今也解释不清楚原因,不过已经找到了解决方案. 先来看看Propagation属性的值含义,@Transactional中Propagation属性有7个选项可供选择: Pr ...

  4. Swift运行时简介

    因为Swift的操作在高层并且也得与Objc联合起来干活,用Swift写的程序一般会被Objc和Swift运行时处理.因为Swift的本性--换句话说,它是一门静态语言--Swift运行时在一些关键地 ...

  5. qq安全原理

    故事总要有缘由,那么这个故事的缘由就是,当我以前写了一个获取其它进程密码框密码的时候(前几篇博客中有描述),我抱着试一试的心情去试探了一下能不能得到 QQ 的密码,当我抓到密码框的句柄,然后输入给程序 ...

  6. 实现memmove函数

    分析:memmove函数是<string.h>的标准函数,其作用是把从source开始的num个字符拷贝到destination.最简单的方法是直接复制,但是由于它们可能存在内存的重叠区, ...

  7. 阻尼回弹效果的ScrollView嵌套GridView

    以前写过一篇带阻尼回弹效果的ScrollView,但是有些小问题,于是又重新整理了一下,这篇文章一是一个带阻尼的Scrollview,再个就是Scrollview嵌套GridView实现,而GridV ...

  8. JAVA面向对象-----抽象类

    1抽象类 为什么使用抽象类 1:定义Dog类 有颜色属性和叫的方法 2:定义Bird类 有颜色属性和叫的方法 3:定义其父类Animal 1:颜色的属性可以使用默认初始化值. 2:叫的方法在父类中如何 ...

  9. DBoW2应用

    图像对应的bag-of-words向量\(v_t\) 假设词典总共有\(W\)个单词,那么每一幅图像能够用一个\(W\)维的向量表示 \((t_1, t_2, t_3, ..., t_W)\)其中 \ ...

  10. UNIX网络编程——epoll 的accept , read, write(重要)

    在一个非阻塞的socket上调用read/write函数,返回EAGAIN或者EWOULDBLOCK(注:EAGAIN就是EWOULDBLOCK). 从字面上看,意思是: EAGAIN: 再试一次 E ...