Nodejs中使用Redis來完成定時任務

若是在Nodesjs開發中你的程序須要執行一些定時任務,你會怎麼作?node

以前的我是這樣作的:git

  1. 打開chromgithub

  2. 在github中查找關鍵字 nodejs 定時任務redis

  3. 選擇star數最高的開源項目.....額,是它 node-schedule。api

而後按照它的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("執行任務");

  });

完成代碼後,個人心情是這樣的。app

呵呵

可是,老大有一天忽然說:你實現的那種方式效率過低了,網上有人用redis實現了定時器。你去看一看,下一版本改成那種實現方式。框架

經過查詢網上的資料和別人的實現方式,大概整理了以下思路。ui

1.Redis 在 2.0.0 以後推出了 Pub / Sub 的指令,能夠訂閱和發送特定頻道消息。
2.Redis 的 2.8.0 版本以後,其推出了一個新的特性——鍵空間消息通知(Redis Keyspace Notifications)
3.就是若是我訂閱了鍵空間消息,那我就能夠完成定時任務了。(通知訂閱緩存的過時事件,獲取對應的key值,使用key值來調用對應任務。 而緩存的過時時間則表示任務的具體執行時間) >.<this

下面是具體實現:

首先你得保證你的Redis版本大於2.8.0。 若是不是的話,那本文到此結束。。

由於Redis默認是關閉鍵空間消息通知功能的,因此需求在配置中更改它,具體配置的方法和參數參考notify-keyspace-events配置

總之最好達到如下的標準就行了。

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. 就是若是你要循環的執行任務。 作法就是你執行一次任務的時候,須要建立下一次任務的緩存。

相關文章
相關標籤/搜索