Redis FIFO任務(wù)隊(duì)列實(shí)現(xiàn)

在實(shí)際的業(yè)務(wù)領(lǐng)域中,常常會異步處理一些任務(wù)鳞陨,這些任務(wù)的執(zhí)行時(shí)間可能會比我們的預(yù)期更長一點(diǎn)颠猴,這些任務(wù)有點(diǎn)需要及時(shí)處理,有的可能需要延時(shí)執(zhí)行坡贺。通常的做法是將這些任務(wù)放入某一種隊(duì)列里面官辈,把工作交給對應(yīng)的任務(wù)處理器去處理。這個(gè)隊(duì)列就是任務(wù)隊(duì)列遍坟,如先進(jìn)先出 (FIFO) 隊(duì)列钧萍、后進(jìn)先出 (LIFO) 隊(duì)列,優(yōu)先級 (Priority) 隊(duì)列以及延時(shí)(Delay)隊(duì)列.

先進(jìn)先出 (FIFO) 隊(duì)列

FIFO 隊(duì)列具有語義清晰政鼠,嚴(yán)格維持任務(wù)發(fā)送和接收的順序處理风瘦,易于實(shí)現(xiàn)等特點(diǎn)。Redis 的列表是簡單的字符串列表公般,按照插入順序排序万搔。允許用戶通過 LPUSH 和 RPUSH 以及 RPOP 和 LPOP 在列表的兩端推入和插入元素,此外還提供了 BRPOP 和BLPOP 連個(gè)阻塞命令官帘,非常適合用于 FIFO 隊(duì)列瞬雹。

定義任務(wù)實(shí)體

創(chuàng)建 taskModel.js 文件,該文件定義了任務(wù)實(shí)體刽虹。一個(gè)任務(wù)通常要包含酗捌,任務(wù)必要的標(biāo)識、任務(wù)的類型涌哲、任務(wù)的行為等等胖缤。

/**
 * 任務(wù)實(shí)體 
 * New node file
 */

function Task(){
    var id
    var type;
    var action;
    
    this.setId = function(theyId){
        id = theyId;
    };
    
    this.setType = function(theyType){
        type = theyType;
    };
    
    this.setAction = function(theyAction){
        action = theyAction;
    };
    
    this.getTaskInfo = function(){
        return  '我的任務(wù) ID 是:  '+ this.id +", 任務(wù)類型 : "+ this.type+", 我的需要完成任務(wù)行為是:"+this.action;
    };
}

module.exports = Task;
創(chuàng)建生產(chǎn)者和消費(fèi)者

創(chuàng)建 main.js 負(fù)責(zé)模擬生產(chǎn)者和消費(fèi)者,為了方便演示阀圾,這里分別使用 addTaskToQueue () 模擬生產(chǎn)者哪廓,getTaskFromQueue 模擬消費(fèi)者。

/**
 * New node file
 */
var Task = require('./taskModel');
const schedule = require('node-schedule');

const app = require('express')();
const PORT = 6379,
      HOST = '127.0.0.1',
      OPTS = {}; // 配置項(xiàng)初烘,比如說設(shè)置密碼 {auth_pass:'123456'},  

//生產(chǎn)者客戶端
const producterClient = require('redis').createClient(PORT, HOST, OPTS);

//消費(fèi)者客戶端
const consumerClient = producterClient.duplicate();

const QUEUE_NAME = 'queue:issue'; 


//添加任務(wù)到隊(duì)列
function addTaskToQueue(){
    
    // 使用 redis 的 incr 生成 id 
    producterClient.incr('id', function(err, id) {
        if(err){
            console.log(err);
        }else{
            var task = new Task();
            task.setId('Task:::'+id);
            task.setType('MESSAGE')
            task.setAction('打印任務(wù)創(chuàng)建的時(shí)間>>>創(chuàng)建時(shí)間:::'+ new Date());
            producterClient.rpush([QUEUE_NAME, task.getTaskInfo()],function(err,reply) {
                if(err){
                    console.log(err);
                }else{
                    console.log('添加任務(wù):'+task.getTaskInfo());
                }   
            });
        }
        
    });
    
    
}

//從任務(wù)隊(duì)列中獲取任務(wù)
function getTaskFromQueue(){
    //使用 blpop 阻塞模式分俯,直到有數(shù)據(jù)返回哆料。blpop 命令每次只會從列表中
    //彈出一個(gè)任務(wù),所以這保證了任務(wù)不會被重復(fù)執(zhí)行杏节。
    producterClient.blpop(QUEUE_NAME, 4,function(err,reply) {
        if(err){
            console.log(err);
        }else{
            if(reply){
                console.log('>>>>>>>>消費(fèi)任務(wù): '+ reply[1]);
            }
        }   
    });
}

// 生產(chǎn)者定時(shí)任務(wù)
let producterJob = schedule.scheduleJob('*/4 * * * * *', () => {
    addTaskToQueue();
});

// 消費(fèi)者定時(shí)任務(wù)
let consumerJob = schedule.scheduleJob('*/2 * * * * *', () => {
    getTaskFromQueue();
});
運(yùn)行結(jié)果:
image.png

總結(jié)

這里使用 List 的特性簡單的模擬了實(shí)現(xiàn)了 FIFO 隊(duì)列拢锹。實(shí)際應(yīng)用中任務(wù)的定義遠(yuǎn)遠(yuǎn)沒有這么簡單卒稳,除了將任務(wù)信息推送到隊(duì)列外他巨,還需要持久化任務(wù)信息。其次捻爷,還需要考慮到客戶端將取得任務(wù)后未及時(shí)處理宕機(jī)導(dǎo)致任務(wù)處理失敗也榄。再者司志,客戶端獲取任務(wù)的指令執(zhí)行成功但是客戶連接超時(shí)斷開連接導(dǎo)致任務(wù)丟失等情況。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末囚霸,一起剝皮案震驚了整個(gè)濱河市激才,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌劣挫,老刑警劉巖钞脂,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異冰啃,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)焚刚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進(jìn)店門矿咕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狼钮,“玉大人熬芜,你說我怎么就攤上這事∪鹞辏” “怎么了鼓拧?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵季俩,是天一觀的道長酌住。 經(jīng)常有香客問我,道長赂韵,這世上最難降的妖魔是什么祭示? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任肄满,我火速辦了婚禮,結(jié)果婚禮上质涛,老公的妹妹穿的比我還像新娘稠歉。我一直安慰自己汇陆,他們只是感情好怒炸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著阅羹,像睡著了一般勺疼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捏鱼,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天,我揣著相機(jī)與錄音导梆,去河邊找鬼轨淌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛看尼,可吹牛的內(nèi)容都是我干的递鹉。 我是一名探鬼主播藏斩,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼躏结,長吁一口氣:“原來是場噩夢啊……” “哼窜觉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎驶睦,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缠导,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡溉痢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年僻造,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片孩饼。...
    茶點(diǎn)故事閱讀 39,764評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡髓削,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出镀娶,到底是詐尸還是另有隱情立膛,我是刑警寧澤,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布梯码,位于F島的核電站宝泵,受9級特大地震影響好啰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鲁猩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一坎怪、第九天 我趴在偏房一處隱蔽的房頂上張望罢坝。 院中可真熱鬧廓握,春花似錦、人聲如沸嘁酿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽闹司。三九已至娱仔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間游桩,已是汗流浹背牲迫。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留借卧,地道東北人盹憎。 一個(gè)月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像铐刘,于是被迫代替她去往敵國和親陪每。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理镰吵,服務(wù)發(fā)現(xiàn)檩禾,斷路器,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,085評論 25 707
  • Java-Review-Note——4.多線程 標(biāo)簽: JavaStudy PS:本來是分開三篇的疤祭,后來想想還是整...
    coder_pig閱讀 1,648評論 2 17
  • 今天是打卡跑步第一百天盼产,感謝一路上陪著我堅(jiān)持到今天的小伙伴們,杭州的魯華菁勺馆、魯晨波戏售、張輝、周晴谓传,廣西的譚宇寧蜈项,深圳...
    獨(dú)行俠者閱讀 510評論 2 5
  • 那一天我二十一歲,在我一生的黃金時(shí)代续挟。我有好多奢望紧卒。我想愛,想吃诗祸,還想在一瞬間變成天上半明半暗的云跑芳。后來我才知道轴总,...
    懸崖邊的稻草人閱讀 516評論 0 0