從原始碼角度研究RocketMQ不僅可以深入研究一款高性能中間件的實作原理,更是可以大大提示編碼能力,更是能加強對高并發等基礎框架的實戰能力,
首先我們來看一下RocketMQ NameServer的路由注冊機制,從中窺探讀寫鎖的使用場景,
1、RocketMQ Nameserver 路由注冊機制

-
Broker 每 30s 向 NameServer 發送心跳包,心跳包中包含主題的路由資訊(主題的讀寫佇列數、操作權限等),NameServer 會通過 HashMap 更新 Topic 的路由資訊,并記錄最后一次收到 Broker 的時間戳,
-
NameServer 以每 10s 的頻率清除已宕機的 Broker,NameServr 認為 Broker 宕機的依據是如果當前系統時間戳減去最后一次收到 Broker 心跳包的時間戳大于 120s,
-
訊息生產者以每 30s 的頻率去拉取主題的路由資訊,即訊息生產者并不會立即感知 Broker 服務器的新增與洗掉,
在上述場景中,Broekr 會定時向 NameServer 匯報路由資訊,即更新操作,消費者、生產在拉取訊息、發送訊息時會經常去查詢 NameServer 中的路由資訊,即所謂的讀操作,
在 Broker NameServer 中使用 HashMap 來存盤 topic 的路由資訊,“眾所周知”HashMap 在多執行緒環境中并不安全,多執行緒環境下,需要加鎖,
如下偽代碼:
public List getTopicInfo(String topicName) {
synchronized(routerInfoHashMap) {
return routerInfoHashMap.get(topicName);
}
}
public void updateTopicInfo(String topicName,List ...) {
synchronized(routerInfoHashMap) {
return routerInfoHashMap.put(topicName, ...);
}
}
上面的代碼有什么缺點呢?
試想一下,如果同一個時間,多個發送者,多個消費者都向nameserver查詢topic的路由資訊,你會發現所有的讀請求都會排隊執行,其并發性能可想而知的低下,此時讀寫鎖就派上用場了,
讀寫鎖的使用如下:


上述代碼來源于org.apache.rocketmq.namesrv.routeinfo.RouteInfoManager,
這樣所有的讀操作能并發執行,極大的提高了性能,
讀寫鎖的規則:讀鎖與寫鎖互斥,讀鎖與讀鎖兼容,即可同時獲取鎖,舉例如下:
例如同一個時間依次有執行緒 t1 t2 t3 申請讀鎖,t4,申請寫鎖,t5 申請讀鎖:
首先 t1,t2,t3 成功獲取鎖,t4,t5阻塞等待,
等t1,t2,t3釋放鎖后,t4獲取鎖,t5阻塞,然后t4釋放鎖,t5獲取鎖,
本文就介紹到這里了,讀寫鎖的使用場景大家是否Get到了,如果本文對你有所幫助,希望一鍵三連表示支持,
見字如面,我是威哥,一個從普通二本院校畢業,從未曾接觸分布式、微服務、高并發到通過技術分享實作職場蛻變,成長為RocketMQ社區優秀布道師、大廠資深架構師,出版《RocketMQ技術內幕》一書,在CSDN中記錄了我的成長歷程,歡迎大家關注,私信,一起交流進步,
分享筆者一個硬核的RocketMQ電子書:

獲取方式:微信搜索【中間件興趣圈】,回復RMQPDF即可獲取,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/271552.html
標籤:其他
上一篇:除了編程語言本身,你如果還懂這 7 點,絕對可以在北上深杭拿到 15k
下一篇:基于深度學習的物體關系抽取
