訊息佇列高手課 筆記8

2022-01-11 20:21:54 字數 3317 閱讀 8007

閘道器如何接收服務端的秒殺結果?

public class requesthandler 

// 查詢秒殺結果

result result = results.remove(uuid);

// 檢查秒殺結果並返回響應

if(null != result && result.success())

} catch (throwable ignored) {}

finally

// 返回秒殺失敗

return response.fail();

} // 在這裡處理後端服務返回的秒殺結果

public void onresult(result result) }}}

詳解 rocketmq 和 kafka 的訊息模型rocketmq 和 kafka 的訊息模型理解的還不是很透徹,這兩個訊息佇列產品的訊息模型是一樣的,我在這裡,再把這個模型相關的概念,通過乙個例子詳細地說一說。

假設有乙個主題 mytopic,我們為主題建立 5 個佇列,分布到 2 個 broker 中。

先說訊息生產這一端,假設我們有 3 個生產者例項:produer0,produer1 和 producer2。

這 3 個生產者是如何對應到 2 個 broker 的,又是如何對應到 5 個佇列的呢?這個很簡單,不用對應,隨便發。每個生產者可以在 5 個佇列中輪詢傳送,也可以隨機選乙個佇列傳送,或者只往某個佇列傳送,這些都可以。比如 producer0 要發 5 條訊息,可以都發到佇列 q0 裡面,也可以 5 個佇列每個佇列發一條。

然後說消費端,很多同學沒有搞清楚消費組、消費者和佇列這幾個概念的對應關係。

每個消費組就是乙份訂閱,它要消費主題 mytopic 下,所有佇列的全部訊息。注意,佇列裡的訊息並不是消費掉就沒有了,這裡的「消費」,只是去佇列裡面讀了訊息,並沒有刪除,消費完這條訊息還是在佇列裡面。

多個消費組在消費同乙個主題時,消費組之間是互不影響的。比如我們有 2 個消費組:g0 和 g1。g0 消費了哪些訊息,g1 是不知道的,也不用知道。g0 消費過的訊息,g1 還可以消費。即使 g0 積壓了很多訊息,對 g1 來說也沒有任何影響。

然後我們再說消費組的內部,乙個消費組中可以包含多個消費者的例項。比如說消費組 g1,包含了 2 個消費者 c0 和 c1,那這 2 個消費者又是怎麼和主題 mytopic 的 5 個佇列對應的呢?

由於消費確認機制的限制,這裡面有乙個原則是,在同乙個消費組裡面,每個佇列只能被乙個消費者例項占用。至於如何分配,這裡面有很多策略,我就不展開說了。總之保證每個佇列分配乙個消費者就行了。比如,我們可以讓消費者 c0 消費 q0,q1 和 q2,c1 消費 q3 和 q4,如果 c0 宕機了,會觸發重新分配,這時候 c1 同時消費全部 5 個佇列。

再強調一下,佇列占用只是針對消費組內部來說的,對於其他的消費組來說是沒有影響的。比如佇列 q2 被消費組 g1 的消費者 c1 占用了,對於消費組 g2 來說,是完全沒有影響的,g2 也可以分配它的消費者來占用和消費佇列 q2。

最後說一下消費位置,每個消費組內部維護自己的一組消費位置,每個佇列對應乙個消費位置。消費位置在服務端儲存,並且,消費位置和消費者是沒有關係的。每個消費位置一般就是乙個整數,記錄這個消費組中,這個佇列消費到哪個位置了,這個位置之前的訊息都成功消費了,之後的訊息都沒有消費或者正在消費。

我把咱們這個例子的消費位置整理成下面的**,便於你理解。

你可以看到,這個**中並沒有消費者這一列,也就是說消費者和消費位置是沒有關係的。

如何實現單個佇列的並行消費?

如果不要求嚴格順序,如何實現單個佇列的並行消費?關於這個問題,有很多的實現方式,在 jmq(京東自研的訊息佇列產品)中,它實現的思路是這樣的。

比如說,佇列中當前有 10 條訊息,對應的編號是 0-9,當前的消費位置是 5。同時來了三個消費者來拉訊息,把編號為 5、6、7 的訊息分別給三個消費者,每人一條。過了一段時間,三個消費成功的響應都回來了,這時候就可以把消費位置更新為 8 了,這樣就實現並行消費。

這是理想的情況。還有可能編號為 6、7 的訊息響應回來了,編號 5 的訊息響應一直回不來,怎麼辦?這個位置 5 就是乙個訊息空洞。為了避免位置 5 把這個佇列卡住,可以先把消費位置 5 這條訊息,複製到乙個特殊重試佇列中,然後依然把消費位置更新為 8,繼續消費。再有消費者來拉訊息的時候,優先把重試佇列中的那條訊息給消費者就可以了。

這是並行消費的一種實現方式。需要注意的是,並行消費開銷還是很大的,不應該作為乙個常規的,提公升消費併發的手段,如果消費慢需要增加消費者的併發數,還是需要擴容佇列數。

如何保證訊息的嚴格順序?

怎麼來保證訊息的嚴格順序?我們多次提到過,主題層面是無法保證嚴格順序的,只有在佇列上才能保證訊息的嚴格順序。

如果說,你的業務必須要求全域性嚴格順序,就只能把訊息佇列數配置成 1,生產者和消費者也只能是乙個例項,這樣才能保證全域性嚴格順序。

大部分情況下,我們並不需要全域性嚴格順序,只要保證區域性有序就可以滿足要求了。比如,在傳遞賬戶流水記錄的時候,只要保證每個賬戶的流水有序就可以了,不同賬戶之間的流水記錄是不需要保證順序的。

如果需要保證區域性嚴格順序,可以這樣來實現。在傳送端,我們使用賬戶 id 作為 key,採用一致性雜湊演算法計算出佇列編號,指定佇列來傳送訊息。一致性雜湊演算法可以保證,相同 key 的訊息總是傳送到同乙個佇列上,這樣可以保證相同 key 的訊息是嚴格有序的。如果不考慮佇列擴容,也可以用佇列數量取模的簡單方法來計算佇列編號。

寫在最後

你先不要太關注功能、api 和配置這些細節,在學習如何使用訊息佇列的過程中,要保持一定的高度來學習。因為使用訊息佇列,大部分的難點在巨集觀架構層面,要解決這些難點,你需要掌握訊息佇列巨集觀層面上的實現原理和最佳實踐,這樣,無論你使用什麼訊息佇列,都可以做到游刃有餘。在選定了合適的訊息佇列產品,準備寫**之前,再去文件中檢視這些細節都來得及。所以,我們專欄的「基礎篇」講訊息佇列的使用,更多講的是一些通用的原理。這節課是我們訊息佇列高手課「基礎篇」的最後一節課,完整基礎篇的學習後,意味著你已經是乙個使用訊息佇列的小達人了。在「高階篇」中,我們將把學習重點從「如何使用」轉為「如何實現」,在學習訊息佇列的實現技術時,你反而要專注到每乙個技術點上,深入下去,把每個細節都要搞清楚、學透。課程的深度、難度也會逐步加強,當然你獲得的經驗值也會更多。希望大家一如既往堅持學習,多思考,多練習,跟老師一起打怪公升級,成為真正的高手。

訊息佇列高手課 筆記1

哪些人適合學訊息佇列?後端開發者 訊息佇列幾乎是每個後端程式設計師都會用到的中介軟體,無論你是開發微服務,實時計算,還是機器學習程式,都需要解決程序間通訊的問題。渴望技術提公升的開發者 訊息佇列所涉及的高效能通訊 海量資料儲存 高併發這些底層的技術比較全面,並且功能簡潔 結構清晰,容易入門但又同時具...

訊息佇列高手課 基礎篇

訊息佇列高手課 基礎篇 訊息佇列都有哪些選擇 rabbitmq 特色 exchange模組,開箱即用 rocketmq 特色 低延遲和金融級的穩定性 kafka 特色 海量,非同步批量,先攢一波再一起處理 activemq 佇列模型和發布 訂閱模型都支援 zeromq pulsar 特色 儲存與計算...

8 程序間通訊 訊息佇列

使用訊息佇列實現程序間的通訊 首先將傳送的資料打包成訊息的型別,使用乙個程序負責將訊息傳送到訊息佇列中,另外乙個程序負責從訊息佇列中接收資訊,從而實現程序間通訊 1 使用訊息佇列通訊的基本流程 1 獲取key值,使用ftok函式 ftok函式 include include key t ftok c...