您好,登錄后才能下訂單哦!
是一個(gè)消息的鏈表,是一個(gè)異步處理的數(shù)據(jù)處理引擎。
PS:可以理解為在redis的list列表中存放消息數(shù)據(jù),然后按照排隊(duì)方式先進(jìn)先出(左進(jìn)右出;右進(jìn)左出)
主要應(yīng)用一些延遲或異步操作的場(chǎng)景
比如:發(fā)送郵件、發(fā)送短信、視頻轉(zhuǎn)碼、圖片轉(zhuǎn)碼、日志存儲(chǔ)、導(dǎo)入數(shù)據(jù)等
在發(fā)送郵件或者短信,我們不希望程序一直停留,等待發(fā)送成功才相應(yīng),而是異步進(jìn)行處理,即:將待發(fā)送的郵件數(shù)據(jù)添加到消息隊(duì)列中,然后按照排隊(duì)先后進(jìn)行異步發(fā)送郵件。
不僅能夠提高系統(tǒng)的負(fù)荷,還能夠改善因網(wǎng)絡(luò)阻塞導(dǎo)致的數(shù)據(jù)缺失
這個(gè)可以理解為:異步處理數(shù)據(jù),不會(huì)一次性給服務(wù)器太多壓力,并且不直接操作數(shù)據(jù)庫(kù),減少了數(shù)據(jù)庫(kù)的壓力;并且若在網(wǎng)絡(luò)阻塞時(shí),若已經(jīng)添加到消息隊(duì)列中,那么這些數(shù)據(jù)會(huì)正常執(zhí)行,不會(huì)造成丟失
整體思路:
前面提到消息隊(duì)列,就相當(dāng)于到銀行窗口排隊(duì),先到的叫號(hào)入隊(duì)(加入到redis消息隊(duì)列),然后排到了則根據(jù)相應(yīng)的叫號(hào)出隊(duì)。
redis的一些特點(diǎn):
redis設(shè)計(jì)用來做緩存的,但是由于它自身的某種特性使得它可以用來做消息隊(duì)列,它有幾個(gè)阻塞式的API可以使用,正是這些阻塞式的API讓其有能力做消息隊(duì)列;另外,做消息隊(duì)列的其他特性例如FIFO(先入先出)也很容易實(shí)現(xiàn),只需要一個(gè)list對(duì)象從頭取數(shù)據(jù),從尾部塞數(shù)據(jù)即可;redis能做消息隊(duì)列還得益于其list對(duì)象blpop brpop接口以及Pub/Sub(發(fā)布/訂閱)的某些接口,它們都是阻塞版的,所以可以用來做消息隊(duì)列。
使用redis的lpush/rpop (rpush/lpop) 命令 簡(jiǎn)單實(shí)現(xiàn)左進(jìn)右出 或 右進(jìn)左出 的list列表。
然后需要開啟一個(gè)線程任務(wù)或者定時(shí)任務(wù)或者輪詢方式,不停的調(diào)用rpop方法查看List中是否有待處理消息。
缺點(diǎn):每調(diào)用一次都會(huì)發(fā)起一次連接,這會(huì)造成不必要的浪費(fèi)。
1)、如果生產(chǎn)者速度大于消費(fèi)者消費(fèi)速度,消息隊(duì)列長(zhǎng)度會(huì)一直增大,時(shí)間久了會(huì)占用大量?jī)?nèi)存空間。
2)、如果睡眠時(shí)間過長(zhǎng),這樣不能處理一些時(shí)效性的消息,睡眠時(shí)間過短,也會(huì)在連接上造成比較大的開銷。
將方案一中的lpop、rpop命令改為使用blpop(左出)、brpop(右出)
這個(gè)指令只有在有元素時(shí)才返回,沒有則會(huì)阻塞直到超時(shí)返回null
阻塞實(shí)現(xiàn):不用輪詢,當(dāng)隊(duì)列key有數(shù)據(jù)時(shí)候,就會(huì)響應(yīng),這里讀取消息不會(huì)一直循環(huán)去讀取,而是一直阻塞,等到有消息過來才讀取。
該指令還提供了優(yōu)先級(jí)以及超時(shí)參數(shù)
實(shí)現(xiàn)隊(duì)列優(yōu)先級(jí)命令:brpop queue1 queue2 ...
這樣子即可以實(shí)現(xiàn)當(dāng)隊(duì)列1有數(shù)據(jù)時(shí),優(yōu)先處理,比如銀行vip窗口等
實(shí)現(xiàn)超時(shí)退出:redis的brpop默認(rèn)不帶超時(shí)參數(shù)(或者說是默認(rèn)為0(s)),會(huì)一直在進(jìn)程中
實(shí)現(xiàn)命令:brpop queue1 timeout
以下使用方案二實(shí)現(xiàn)思路
例子:發(fā)送平臺(tái)用戶郵箱消息通知(可以多場(chǎng)景、如發(fā)送驗(yàn)證碼、重置密碼等等)
# 第一步 請(qǐng)求發(fā)送的平臺(tái)用戶信息進(jìn)隊(duì)
//...... 獲取用戶信息代碼省略
$userInfo = ['id'=>1, 'name'=>'張三', 'email'=>'393364227@qq.com'];
$redis->lpush('sendEmailQueue', serialize($userInfo)); //serialize 序列化數(shù)組信息,轉(zhuǎn)為字符串
//..... 同步處理,相應(yīng)頁(yè)面 發(fā)送成功等信息
# 第二步 在另一個(gè)接口類出隊(duì),并且處理消息
$userInfo = unserialize(brpop('sendEmailQueue'));
//sendEmail 開始發(fā)送郵件操作
# 第三步 將第二步的實(shí)現(xiàn)接口添加到進(jìn)程任務(wù),并且開啟進(jìn)程保護(hù)
//可以使用linux下的Supervisor來做進(jìn)程保護(hù)
//啟動(dòng)隊(duì)列進(jìn)程,即可實(shí)現(xiàn)消息隊(duì)列去發(fā)送郵件了
The End.
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。