用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. if-case-循环语句

    IF语句 drop procedure if exists p_hello_world; create procedure p_hello_world(in v_id int) begin ) the ...

  2. Python3 条件控制

    if 语句 Python中if语句的一般形式如下所示: if condition_1: statement_block_1 elif condition_2: statement_block_2 el ...

  3. 弹出层之2:JQuery.BlockUI

    JQuery.BlockUI是众多JQuery插件弹出层中的一个,它小巧(原版16k,压缩后10左右),容易使用, 功能齐全,支持Iframe,支持Modal,可定制性高也意味他默认谦虚的外表. jQ ...

  4. Activtiy完全解析(二、layout的inflate过程)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/52457893 本文出自:[openXu的博客]   在上一篇文章<Activtiy完全 ...

  5. mysql进阶(二十九)常用函数

    mysql进阶(二十九)常用函数 一.数学函数 ABS(x) 返回x的绝对值 BIN(x) 返回x的二进制(OCT返回八进制,HEX返回十六进制) CEILING(x) 返回大于x的最小整数值 EXP ...

  6. 基于Nginx服务器和iOS9的HTTPS安全通信

    简介 在网络通信中,使用抓包软件可以对网络请求进行分析,并进行重放攻击,重放攻击的解决方案一般是使用一个变化的参数,例如RSA加密的时间戳,但考虑到网络传输时延,时间戳需要有一定的误差容限,这样仍然不 ...

  7. Effective C++ ——资源管理

    条款13:以对象来管理资源 在C++中我们经常会涉及到资源的申请与申请,一般都是由关键字new 和 delete来操作的,两者都是成对存在的,缺一不可,否则会出现意想不到的问题,例如: class I ...

  8. 开源框架Slidingmenu的基本使用

    转载本博客请标明出处:点击打开链接      http://blog.csdn.net/qq_32059827/article/details/52464262 侧滑菜单在开发中经常用到,而Slidi ...

  9. [ExtJS5学习笔记]第十六节 Extjs5使用panel新增的ViewModel属性绑定数据

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/39078627 sencha官方API:http://docs.sencha.com/e ...

  10. Spark技术内幕: Task向Executor提交的源码解析

    在上文<Spark技术内幕:Stage划分及提交源码分析>中,我们分析了Stage的生成和提交.但是Stage的提交,只是DAGScheduler完成了对DAG的划分,生成了一个计算拓扑, ...