1. 程式人生 > >redis消息隊列簡單應用

redis消息隊列簡單應用

linux下 如果 pre 占用 不能 sub 引擎 空間 iso

參考 https://blog.yxccan.cn/blog/detail/3

一、什麽是消息隊列

是一個消息的鏈表,是一個異步處理的數據處理引擎。

PS:可以理解為在redis的list列表中存放消息數據,然後按照排隊方式先進先出(左進右出;右進左出)

二、可以使用的應用場景

主要應用一些延遲或異步操作的場景
比如:發送郵件、發送短信、視頻轉碼、圖片轉碼、日誌存儲、導入數據等
在發送郵件或者短信,我們不希望程序一直停留,等待發送成功才相應,而是異步進行處理,即:將待發送的郵件數據添加到消息隊列中,然後按照排隊先後進行異步發送郵件。

三、優點

不僅能夠提高系統的負荷,還能夠改善因網絡阻塞導致的數據缺失
這個可以理解為:異步處理數據,不會一次性給服務器太多壓力,並且不直接操作數據庫,減少了數據庫的壓力;並且若在網絡阻塞時,若已經添加到消息隊列中,那麽這些數據會正常執行,不會造成丟失

四、redis實現隊列方案

整體思路:
前面提到消息隊列,就相當於到銀行窗口排隊,先到的叫號入隊(加入到redis消息隊列),然後排到了則根據相應的叫號出隊。

redis的一些特點:
redis設計用來做緩存的,但是由於它自身的某種特性使得它可以用來做消息隊列,它有幾個阻塞式的API可以使用,正是這些阻塞式的API讓其有能力做消息隊列;另外,做消息隊列的其他特性例如FIFO(先入先出)也很容易實現,只需要一個list對象從頭取數據,從尾部塞數據即可;redis能做消息隊列還得益於其list對象blpop brpop接口以及Pub/Sub(發布/訂閱)的某些接口,它們都是阻塞版的,所以可以用來做消息隊列。

方案一:

使用redis的lpush/rpop (rpush/lpop) 命令 簡單實現左進右出 或 右進左出 的list列表。
然後需要開啟一個線程任務或者定時任務或者輪詢方式,不停的調用rpop方法查看List中是否有待處理消息。
缺點:每調用一次都會發起一次連接,這會造成不必要的浪費。
1)、如果生產者速度大於消費者消費速度,消息隊列長度會一直增大,時間久了會占用大量內存空間。
2)、如果睡眠時間過長,這樣不能處理一些時效性的消息,睡眠時間過短,也會在連接上造成比較大的開銷。

方案二:(推薦)

將方案一中的lpop、rpop命令改為使用blpop(左出)、brpop(右出)
這個指令只有在有元素時才返回,沒有則會阻塞直到超時返回null

阻塞實現:不用輪詢,當隊列key有數據時候,就會響應,這裏讀取消息不會一直循環去讀取,而是一直阻塞,等到有消息過來才讀取。
該指令還提供了優先級以及超時參數
實現隊列優先級命令:brpop queue1 queue2 ...
這樣子即可以實現當隊列1有數據時,優先處理,比如銀行vip窗口等
實現超時退出:redis的brpop默認不帶超時參數(或者說是默認為0(s)),會一直在進程中
實現命令:brpop queue1 timeout

五、代碼實現思路

以下使用方案二實現思路
例子:發送平臺用戶郵箱消息通知(可以多場景、如發送驗證碼、重置密碼等等)

# 第一步 請求發送的平臺用戶信息進隊

//...... 獲取用戶信息代碼省略
$userInfo = [‘id‘=>1, ‘name‘=>‘張三‘, ‘email‘=>‘[email protected]‘];
$redis->lpush(‘sendEmailQueue‘, serialize($userInfo)); //serialize 序列化數組信息,轉為字符串
//..... 同步處理,相應頁面 發送成功等信息

# 第二步 在另一個接口類出隊,並且處理消息

$userInfo = unserialize(brpop(‘sendEmailQueue‘));
//sendEmail 開始發送郵件操作

# 第三步 將第二步的實現接口添加到進程任務,並且開啟進程保護
//可以使用linux下的Supervisor來做進程保護
//啟動隊列進程,即可實現消息隊列去發送郵件了

The End.


redis消息隊列簡單應用