
這些用起來都是比較複雜的,RabbitMQ先要建立Exchange,在建立Queue,還要将Queue和Exchange通過某種規則綁定起來。發消息之前要指定routing-Key,還要控制頭部資訊。
即使你隻需要一組消息者。那麼你就要經曆上面繁瑣的過程。
但是Redis對于那些輕量級和隻有一組消息者的消息隊列;
Redis的list資料結構常用來作為異步消息隊列來使用。使用rpush/lpush操作入隊列,用lpop/rpop來出隊列。我們都知道list是一個連結清單,是以操作方式如下
當然我們會遇到一些問題,比如隊列空了會怎麼樣?用戶端是通過隊列的 pop 操作來擷取消息,然後進行處理。處理完了再接着擷取消息,再進行處理。如此循環往複,這便是作為隊列消費者的用戶端的生命周期。 可是如果隊列空了,用戶端就會陷入 pop 的死循環,不停地 pop,沒有資料,接着再 pop,又沒有資料。這就是浪費生命的空輪詢。空輪詢不但拉高了用戶端的 CPU,redis 的 QPS 也會被拉高,如果這樣空輪詢的用戶端有幾十來個,Redis 的慢查詢可能會顯著增多。 通常我們使用 sleep 來解決這個問題,讓線程睡一會,睡個 1s 鐘就可以了。不但用戶端的 CPU 能降下來,Redis 的 QPS 也降下來了。(摘自Redis深度曆險)
睡眠會導緻消息的延遲增大·,多個消費者情況下,延遲會有所下降,因為每個消費者都是的睡眠時間是岔開來的。通過阻塞讀:blocking,也就是這兩個指令:blpop,brpop。
當然還有會空閑連接配接自動斷開,顧名思義,一直阻塞,Redis用戶端就成了閑置的,時間長了,伺服器會斷開連接配接,減少閑置資源,這時候就會抛出異常,是以編寫消費者的時候,注意捕獲異常,重試。
延時隊列:
這種方式比較适合異步消息處理,将目前沖突的請求扔到另一個隊列延後處理以避開沖突
我們将消息序列化成一個字元串作為 zset 的 value,這個消息的到期處理時間作為 score,然後用多個線程輪詢 zset 擷取到期的任務進行處理,多個線程是為了保障可用性,萬一挂了一個線程還有其它線程可以繼續處理。因為有多個線程,是以需要考慮并發争搶任務,確定任務不能被多次執行。