參考 blog.yxccan.cn/blog/detail…
第一次寫掘金部落格,小夥伴萌,多多支援喲~(^__^) 嘻嘻
一、什麼是訊息佇列
是一個訊息的連結串列,是一個非同步處理的資料處理引擎。
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'=>'393364227@qq.com'];
$redis->lpush('sendEmailQueue', serialize($userInfo)); //serialize 序列化陣列資訊,轉為字串
//..... 同步處理,相應頁面 傳送成功等資訊
# 第二步 在另一個介面類出隊,並且處理訊息
$userInfo = unserialize(brpop('sendEmailQueue'));
//sendEmail 開始傳送郵件操作
# 第三步 將第二步的實現介面新增到程式任務,並且開啟程式保護
//可以使用linux下的Supervisor來做程式保護
//啟動佇列程式,即可實現訊息佇列去傳送郵件了
複製程式碼
The End.