[Redis]处理定时任务的2种思路

http://blog.csdn.net/orangleliu/article/details/52038092

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"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

上面的测试直接把小于当前时间戳的所有任务都做了一遍,会有些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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

利用键过期通知

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

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

notify-keyspace-events Ex
  • 1
  • 1

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

liuzhizhi@lzz-rmbp|redis_test # redis-cli --csv psubscribe ‘[email protected]__: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"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

第二个窗口 设置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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

小结

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

时间: 2024-11-02 17:01:35

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

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

PHP实现执行定时任务的几种思路详解 php 定时任务 唐霜 2015年07月03日发布 推荐 7 推荐 收藏 65 收藏,11.1k 浏览 PHP本身是没有定时功能的,PHP也不能多线程.PHP的定时任务功能必须通过和其他工具结合才能实现,例如WordPress内置了wp-cron的功能,很厉害.本文,我们就来深入的解析几种常见的php定时任务的思路. Linux服务器上使用CronTab定时执行php 我们先从相对比较复杂的服务器执行php谈起.服务器上安装了php,就可以执行php文件,无

Android JSON原生解析的几种思路,以号码归属地,笑话大全,天气预报为例演示

Android JSON原生解析的几种思路,以天气预报为例 今天项目中要实现一个天气的预览,加载的信息很多,字段也很多,所以理清了一下思路,准备独立出来写一个总结,这样对大家还是很有帮助的,老司机要开车了 涉及到网络,你就一定要先添加权限,准没错 <!--网络权限--> <uses-permission android:name="android.permission.INTERNET" /> 一.归属地查询(JSONObject) 这个也是最简单的一类Json

Reorder List [leetcode] 这两种思路

第一个想法随着vector保存全部Node* 表拼接出来 void reorderList(ListNode *head) { vector<ListNode*> content; ListNode * cur = head; while (cur) { content.push_back(cur); cur = cur->next; } int size = content.size(); cur = NULL; for (int i = 0; i <= size - 1 - i

解决session共享的几种思路

session与cookie的区别在于:session是保存在服务器端,cookie保存在客户端.session怎么样保存的?以文件的形式保存. 第一种办法:把原来存储在服务器磁盘上的session数据存储到客户端的cookie中去.php由原来的"从本地(也就是服务器)磁盘上读取session数据"转变为"浏览器的cookie中读取数据",一般是把session数据按照自己定义的加密规则,加密后后存在cookie中.数据保存在cookie中这种做法有好处,也有坏处

PHP 两个多维数组根据某个键的值进行组合排序的几种思路

需求: 有两个多维数组 $arr = [ ['name'=>'dee','age'=>28], ['name'=>'emperor', 'age'=>30], ['name'=>'Lee', 'age'=>32], ['name'=>'Arshavin', 'age'=>33] ]; $arr2 = [ ['name'=>'Ozil', 'age'=>27], ['name'=>'CR7', 'age'=>29], ['name'=&

java实现定时任务的三种方法

java实现定时任务的三种方法 详解java定时任务 定时器的实现.java定时器介绍与Spring中定时器的配置 java定时器简单了解 ------------------ java定时器执行多个方法

Reorder List [leetcode] 的两种思路

第一种思路是用一个vector存所有的Node* 之后再用两个指针将链表拼接出来 void reorderList(ListNode *head) { vector<ListNode*> content; ListNode * cur = head; while (cur) { content.push_back(cur); cur = cur->next; } int size = content.size(); cur = NULL; for (int i = 0; i <=

Spring定时任务的几种实现

Spring定时任务的几种实现: 近日项目开发中需要执行一些定时任务,比如需要在每天凌晨时候,分析一次前一天的日志信息,借此机会整理了一下定时任务的几种实现方式,由于项目采用spring框架,所以我都将结合 spring框架来介绍. 一.分类 从实现的技术上来分类,目前主要有三种技术(或者说有三种产品): Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执行,也能在指定时间运行.一般用的较少,

数据分析常见的七种思路

数据分析常见的七种思路:1.简单趋势通过访问趋势了解产品使用情况,便于产品迭代.访问用户量.访问来源.访问用户行为三大指标对于趋势分析具有重要意义.2.多维分解根据分析需要,从多维度对指标进行分解.例如浏览器类型.操作系统类型.访问来源.广告来源.地区.网站/手机应用.设备品牌.APP版本等维度.3.转化漏斗按照已知的转化路径,借助漏斗模型分析总体和每一步的转化情况.常见的转化情境有注册转化分析.购买转化分析等.4.用户分群在精细化分析中,常常需要对有某个特定行为的用户群组进行分析和比对:需要将