這是一道面試中常見的 Redis 基礎面試題,主要考察求職者對於 Redis 應用場景的瞭解。
即使不準備面試也建議看看,實際開發中也能夠用到。
內容概覽:
關於 Redis 實現分散式鎖的詳細介紹,可以看我寫的這篇文章:如何基於 Redis 實現分散式鎖?。
實際專案中也沒見誰使用 Redis 來做訊息佇列,對於這部分知識點大家瞭解就好了。
先說結論:可以是可以,但不建議使用 Redis 來做訊息佇列。和專業的訊息佇列相比,還是有很多欠缺的地方。
Redis 2.0 之前,如果想要使用 Redis 來做訊息佇列的話,只能通過 List 來實現。
通過 RPUSH/LPOP
或者 LPUSH/RPOP
即可實現簡易版訊息佇列:
# 生產者生產訊息
> RPUSH myList msg1 msg2
(integer) 2
> RPUSH myList msg3
(integer) 3
# 消費者消費訊息
> LPOP myList
"msg1"
不過,通過 RPUSH/LPOP
或者 LPUSH/RPOP
這樣的方式存在效能問題,我們需要不斷輪詢去呼叫 RPOP
或 LPOP
來消費訊息。當 List 為空時,大部分的輪詢的請求都是無效請求,這種方式大量浪費了系統資源。
因此,Redis 還提供了 BLPOP
、BRPOP
這種阻塞式讀取的命令(帶 B-Bloking 的都是阻塞式),並且還支援一個超時引數。如果 List 為空,Redis 伺服器端不會立刻返回結果,它會等待 List 中有新資料後在返回或者是等待最多一個超時時間後返回空。如果將超時時間設定為 0 時,即可無限等待,直到彈出訊息
# 超時時間為 10s
# 如果有資料立刻返回,否則最多等待10秒
> BRPOP myList 10
null
List 實現訊息佇列功能太簡單,像訊息確認機制等功能還需要我們自己實現,最要命的是沒有廣播機制,訊息也只能被消費一次。
Redis 2.0 引入了釋出訂閱 (pub/sub) 功能,解決了 List 實現訊息佇列沒有廣播機制的問題。
pub/sub 中引入了一個概念叫 channel(頻道),釋出訂閱機制的實現就是基於這個 channel 來做的。
pub/sub 涉及釋出者(Publisher)和訂閱者(Subscriber,也叫消費者)兩個角色:
PUBLISH
投遞訊息給指定 channel。SUBSCRIBE
訂閱它關心的 channel。並且,訂閱者可以訂閱一個或者多個 channel。我們這裡啟動 3 個 Redis 使用者端來簡單演示一下:
pub/sub 既能單播又能廣播,還支援 channel 的簡單正則匹配。不過,訊息丟失(使用者端斷開連線或者 Redis 宕機都會導致訊息丟失)、訊息堆積(釋出者釋出訊息的時候不會管消費者的具體消費能力如何)等問題依然沒有一個比較好的解決辦法。
為此,Redis 5.0 新增加的一個資料結構 Stream
來做訊息佇列。Stream
支援:
Stream
使用起來相對要麻煩一些,這裡就不演示了。而且,Stream
在實際使用中依然會有一些小問題不太好解決比如在 Redis 發生故障恢復後不能保證訊息至少被消費一次。
綜上,和專業的訊息佇列相比,使用 Redis 來實現訊息佇列還是有很多欠缺的地方比如訊息丟失和堆積問題不好解決。因此,我們通常建議不要使用 Redis 來做訊息佇列,你完全可以選擇市面上比較成熟的一些訊息佇列比如 RocketMQ、Kafka。
相關閱讀:Redis 訊息佇列發展歷程 - 阿里開發者 - 2022。