之前的我是这样做的:
1.
打开
chrom
2.
在
github
中查找关键字
nodejs
定时任务
3.
选择
star
数最高的开源项目
.....
额,是它
node-schedule
。
然后按照它的api,
写类似以下的代码,基本就能把功能完成了
//
确定时间的任务,在
2015
年
10
月
1
日,
00:00:00
执行
var schedule = require("node-schedule");
var date =
new Date(2015,10,1,0,0,0);
var job = schedule.scheduleJob(date,
function(){
console.log("
执行任务
");
});
但是,老大有一天突然说:你实现的那种方式效率太低了,网上有人用redis
实现了定时器。你去看一看,下一版本改为那种实现方式。
通过查询网上的资料和别人的实现方式,大概整理了如下思路。
1.Redis
在
2.0.0
之后推出了
Pub / Sub
的指令,可以订阅和发送特定频道消息。
2.Redis
的
2.8.0
版本之后,其推出了一个新的特性
——
键空间消息通知
3.
就是如果我订阅了键空间消息,那我就可以完成定时任务了。(通知订阅缓存的过期事件,获取对应的
key
值,使用
key
值来调用对应任务。 而缓存的过期时间则表示任务的具体执行时间)
>.<
下面是具体实现:
首先你得保证你的Redis
版本大于
2.8.0
。 如果不是的话,那本文到此结束。
因为Redis
默认是关闭键空间消息通知功能的,所以需求在配置中更改它,
最好达到以下的标准就好了。
notify-keyspace-
events Ex
接下来都是代码了:
本次功能是基于
sails
框架完成的。
首先,要在项目启动的时候开启一个Redis
专门用来订阅键空间通知
var redis =
require("redis");//
创建一个用于订阅通知的
client
var subscriberClient = redis.createClient( );
function
initRedisSubscribe() {
return subscriberClient.psubscribe('__keyevent@' + 1 +'__:expired');
}
然后,你需要创建定时任务的地方,创建一条Redis
缓存,过期时间为你想执行任务的时间减去当前时刻。设置任务:
var redis =
require("redis");//
创建一个用于创建任务的
client
var schedQueueClient = redis.createClient( );
function
setProductTask(key) {
return schedQueueClient.PSETEX(key, , '');
}
原理就是当缓存过期是,通过之前的订阅,我们能获取到缓存的key
值,根据
key
值我们能够执行对应的任务。
大概是这样的:
//
当接收到订阅消息调用对应服务
subscriberClient.on("pmessage", function (pattern, channel, expiredKey) {
var taskname = expiredKey;
switch(taskname)
{
case 'oneTask':
return ProductTaskService[taskname].apply(
this,_task);
break;
case 'twoTask':
return SitemapTaskService[taskname].apply(
this,_task);
break;
default:
break;
}
});
其中,我遇到比较大的俩个问题。
1.
就是时间不好处理,因为不能像之前使用
new Date(2015,10,1,0,0,0)
这样来设置任务的时间了, 最好用了万能的时间库
moment
来解决问题
2.
就是如果你要循环的执行任务。 做法就是你执行一次任务的时候,需要创建下一次任务的缓存。
文章来源:SegmentFault