1. 程式人生 > >Disruptor併發框架(二)

Disruptor併發框架(二)

核心術語

  • RingBuffer(容器): 被看作Disruptor最主要的元件,然而從3.0開始RingBuffer僅僅負責儲存和更新在Disruptor中流通的資料。對一些特殊的使用場景能夠被使用者(使用其他資料結構)完全替代。
  • Sequence(槽位置): Disruptor使用Sequence來表示一個特殊元件處理的序號。和Disruptor一樣,每個消費者(EventProcessor)都維持著一個Sequence。大部分的併發程式碼依賴這些Sequence值的運轉,因此Sequence支援多種當前為AtomicLong類的特性。
  • Sequencer: 這是Disruptor真正的核心。實現了這個介面的兩種生產者(單生產者和多生產者)均實現了所有的併發演算法,為了在生產者和消費者之間進行準確快速的資料傳遞。
  • SequenceBarrier(生產消費者衝突問題解決): 由Sequencer生成,並且包含了已經發布的Sequence的引用,這些的Sequence源於Sequencer和一些獨立的消費者的Sequence。它包含了決定是否有供消費者來消費的Event的邏輯。
  • WaitStrategy:決定一個消費者將如何等待生產者將Event置入Disruptor。
  • Event:從生產者到消費者過程中所處理的資料單元。Disruptor中沒有程式碼表示Event,因為它完全是由使用者定義的。
  • EventProcessor(生產執行緒):主要事件迴圈,處理Disruptor中的Event,並且擁有消費者的Sequence。它有一個實現類是BatchEventProcessor,包含了event loop有效的實現,並且將回調到一個EventHandler介面的實現物件。
  • EventHandler(消費者):由使用者實現並且代表了Disruptor中的一個消費者的介面。
  • Producer:由使用者實現,它呼叫RingBuffer來插入事件(Event),在Disruptor中沒有相應的實現程式碼,由使用者實現。
  • WorkProcessor:確保每個sequence只被一個processor消費,在同一個WorkPool中的處理多個WorkProcessor不會消費同樣的sequence。
  • WorkerPool:一個WorkProcessor池,其中WorkProcessor將消費Sequence,所以任務可以在實現WorkHandler介面的worker吃間移交
  • LifecycleAware:當BatchEventProcessor啟動和停止時,於實現這個介面用於接收通知。

初看Disruptor,給人的印象就是RingBuffer是其核心,生產者向RingBuffer中寫入元素,消費者從RingBuffer中消費元素,如下圖:

ringbuffer究竟是什麼?

  • 正如名字所說的一樣,它是一個環(首尾相接的環),你可以把它用做在不同上下文(執行緒)間傳遞資料的buffer

  • ringbuffer擁有一個序號,這個序號指向陣列中下一個可用元素

Disruptor說的是生產者和消費者的故事. 有一個數組.生產者往裡面扔芝麻.消費者從裡面撿芝麻. 但是扔芝麻和撿芝麻也要考慮速度的問題. 1 消費者撿的比扔的快 那麼消費者要停下來.生產者扔了新的芝麻,然後消費者繼續. 2 陣列的長度是有限的,生產者到末尾的時候會再從陣列的開始位置繼續.這個時候可能會追上消費者,消費者還沒從那個地方撿走芝麻,這個時候生產者要等待消費者撿走芝麻,然後繼續.

進一步理解

1如果你看了維基百科裡面的關於環形buffer的詞條,你就會發現,我們的實現方式,與其最大的區別在於:沒有尾指標。我們只維護了一個指向下一個可用位置的序號。這種實現是經過深思熟慮的—我們選擇用環形buffer的最初原因就是想要提供可靠的訊息傳遞。
2我們實現的ring buffer和大家常用的佇列之間的區別是,我們不刪除buffer中的資料,也就是說這些資料一直存放在buffer中,直到新的資料覆蓋他們。這就是和維基百科版本相比,我們不需要尾指標的原因。ringbuffer本身並不控制是否需要重疊。
3因為它是陣列,所以要比連結串列快,而且有一個容易預測的訪問模式。
4這是對CPU快取友好的,也就是說在硬體級別,陣列中的元素是會被預載入的,因此在ringbuffer當中,cpu無需時不時去主存載入陣列中的下一個元素。
5其次,你可以為陣列預先分配記憶體,使得陣列物件一直存在(除非程式終止)。這就意味著不需要花大量的時間用於垃圾回收。此外,不像連結串列那樣,需要為每一個新增到其上面的物件創造節點物件—對應的,當刪除節點時,需要執行相應的記憶體清理操作。