Disruptor-架構思惟的轉變

相對於無鎖技術,Disruptor對於架構思惟的轉變,纔是其最大亮點。html

Pub Event

說到RingBuffer作的隊列,一般都說的是「一讀一寫「,或者「多讀一寫「。而Disruptor天生是爲「廣播「設計,也就是1個Producer,多個Consumer消費同1條消息。服務器

有了「廣播「,就能很好的支持不一樣邏輯模塊的並行計算,從而提升性能。下面會專門分析一個案例,來討論這個並行計算。網絡

Consumer依賴關係維護

假設有以下一個場景:1個生成者P1,3個消費者C1, C2, C3。其中C3要依賴C1, C2執行完畢。若是基於傳統的消息隊列來設計,就會是以下的菱形結構:
這裏寫圖片描述架構

之間用4個隊列來鏈接,從P1流經到C3,要通過這4個隊列。性能

而若是用Disruptor的話,將只須要一個RingBuffer,3個consumer都消費這同1個RingBuffer,以下圖所示:測試

這裏寫圖片描述

在這裏,有幾個關鍵點:
(1)C1, C2, C3消費的是同一個RingBuffer,由於進度不同,它們各自有本身的指針,稱之爲Sequence。這裏假設爲S1, S2, S3spa

(2)C3是要依賴C1, C2的,也就是它要等C1, C2消費完以後,它才能消費。所以S3取的是Min(S1, S2)。.net

(3)假設P1的指針是S0,P1只須要和S3比較就好了,而不須要和S1, S2比較。由於S3是消費最慢的,只要P1沒有跟上S3,那麼隊列就不會被覆蓋。設計

依賴關係的表達

具體到Disruptor中,如何表達C3依賴C1, C2呢?代碼舉例以下,很簡單:指針

//handler1, 2, 3, 4同時消費一個RingBuffer,2, 3, 4並行,同時依賴1 disruptor.handleEventsWith(handler1).then(handler2, handler3, handler4); //handler1,2,3,4同時消費一個RingBuffer,2依賴1,3依賴2,4依賴3 disruptor.handleEventsWith(handler1).then(handler2).then(handler3).then(handler4); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Event Resourcing

在Marin Flower介紹LMAX的價格的時候,http://martinfowler.com/articles/lmax.html

提出了一種思想:Event Resourcing
http://martinfowler.com/eaaDev/EventSourcing.html

下面以LMAX的架構爲例,來說解這種思想:
這裏寫圖片描述

如上圖所示,Receiver接收請求(這裏的Receiver你能夠理解爲一個網絡服務器),BLP處理請求,Publisher把處理結果交給下游。

在這裏,BLP是純粹在內存中操做,那它掛了以後,狀態怎麼恢復呢?這裏有3個關鍵點:
(1)在BLP處理每個Event以前,該Event先被Journaler日誌化
(2)BLP自己是個狀態機。即便掛了,能夠重放全部日誌,恢復狀態。另外,爲了提升恢復速度,BLP的狀態能夠按期作Snapshot。
(3)爲了提升HA,能夠準備多個BLP並行,1個掛了,切換到其它的。因此有一個Replicator組件,用於複製日誌。

在這裏,Receiver、BLP、Journaler、Replicator經過一個RingBuffer進行交互,以下圖所示:

這裏寫圖片描述

在這裏有1個Producer,4個Consumer,前3個能夠並行,最後一個BLP依賴前3個。

Un-marshaller在這裏作一些Event的解析工做。

這種架構還有一個巨大優勢就是:可測性。你能夠把日誌拷貝到測試環境,「重放「整個過程來測試BLP。

總結

經過上面的分析,咱們會發現Disruptor並非咱們一般意義上的一個簡單的RingBuffer。

基於它LMAX設計了一個新的架構,這種架構不只速度夠快,並且具備持久性、HA、可測性等諸多優勢。

--------------------- 本文來自 travi 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/chunlongyu/article/details/53313575?utm_source=copy 

相關文章
相關標籤/搜索