本發(fā)明涉及計算機技術領域,特別是涉及一種基于Disruptor的數(shù)據(jù)收發(fā)方法。
背景技術:
在大規(guī)模的數(shù)據(jù)處理中,為了實現(xiàn)高性能(低延遲、低資源耗用等)系統(tǒng),如電子商務系統(tǒng),金融交易系統(tǒng)等。工程師們會結合現(xiàn)代計算機處理器(CPU)的特點,設計多任務、多線程的架構。這些運行的任務線程,可以爭用處理器計算時間,各自獨立執(zhí)行,最終完成同一個或不同的處理任務,這就是我們說的并發(fā)。并發(fā)程序中通常會發(fā)生針對同一程序對象或計算機資源的搶占爭用,為了保證這種對某一資源對象的訪問操作是安全有序(即線程安全)的,必須為它們設計相應的鎖,即我們通常講的并發(fā)同步鎖。所以就很容易看到“申請鎖”、“讀寫數(shù)據(jù)對象(操作資源對象)”、“釋放鎖”的循環(huán)反復情景。在各種架構中,都有專門的、支持并發(fā)任務處理的實現(xiàn),如Java中的線程池ThreadPoolExecutor。
在生產(chǎn)者-消費者場景中,如果生產(chǎn)者和消費者分別使用不同的線程實現(xiàn),那么這一模型的實質就是不同線程對數(shù)據(jù)的共享和傳遞。而在當前普遍的架構中,是使用隊列(Queue)來共享數(shù)據(jù),生產(chǎn)者線程將消息產(chǎn)出后,放入隊列,消費者線程從該隊列中獲取消息并處理。消息因此得到了傳遞。所以,隊列也可以看成是消息的緩沖區(qū)。這種架構允許生產(chǎn)線程在消費線程處理不過來的情況下,還可以繼續(xù)后面的工作。在Java中,對于隊列(Queue)來說,BlockingQueue是主要的線程安全版本。
基于BlockingQueue和ThreadPoolExecutor這一典型的傳統(tǒng)技術方案。雖然它幫助實現(xiàn)了異步的、較高性能的并發(fā)消息處理,但隨著業(yè)務增長和上游子系統(tǒng)提交的消息量增加,該方案的缺點也顯露無疑。這是因為,這種任務處理機制存在以下明顯的不足(缺點):
(1)BlockingQueue和ThreadPoolExecutor中的并發(fā)同步鎖無處不在。而鎖技術是慢的,代價昂貴。因為它依賴底層操作系統(tǒng),這導致消息的處理延遲較高。
(2)線程需要申請CPU時間窗口以便執(zhí)行。數(shù)量眾多的線程間的上下文切換,意味著頻繁的CPU計算資源調(diào)度。最終的結果就是,整體的消息處理性能和吞吐量并不能隨著線程數(shù)量的增加而線性提升。
由此可見,在數(shù)據(jù)收發(fā)過程中,如何克服BlockingQueue和ThreadPoolExecutor所帶來的問題是本領域技術人員亟待解決的問題。
技術實現(xiàn)要素:
本發(fā)明的目的是提供一種基于Disruptor的數(shù)據(jù)收發(fā)方法,用于在數(shù)據(jù)收發(fā)過程中,克服BlockingQueue和ThreadPoolExecutor所帶來的問題。
為解決上述技術問題,本發(fā)明提供一種基于Disruptor的數(shù)據(jù)收發(fā)方法,用于數(shù)據(jù)處理系統(tǒng),包括:
當接收到上游子系統(tǒng)的待處理數(shù)據(jù)時,事件處理器獲取Disruptor下的RingBuffer的當前最新寫入數(shù)據(jù)的序列號,并將所述待處理數(shù)據(jù)寫入所述序列號所在槽的下一個空閑槽;
所述RingBuffer將當前最新寫入數(shù)據(jù)的序列號加1并公布,然后通知事件監(jiān)聽處理器以進行數(shù)據(jù)的消費和處理。
優(yōu)選地,所述RingBuffer中的槽的數(shù)量為2n,其中,n為正整數(shù)。
優(yōu)選地,所述序列號與所述槽的位置號相同。
優(yōu)選地,所述事件處理器通過基于Netty的數(shù)據(jù)傳輸協(xié)議接收所述上游子系統(tǒng)的待處理數(shù)據(jù)。
優(yōu)選地,所述Disruptor支持單個生產(chǎn)者模式或多個生產(chǎn)者模式。
優(yōu)選地,還包括:
所述事件監(jiān)聽處理器通過ExecutorService提供的線程池觸發(fā)所述數(shù)據(jù)的消費和處理。
本發(fā)明所提供的基于Disruptor的數(shù)據(jù)收發(fā)方法,用于數(shù)據(jù)處理系統(tǒng),包括:當接收到上游子系統(tǒng)的待處理數(shù)據(jù)時,事件處理器獲取Disruptor下的RingBuffer的當前最新寫入數(shù)據(jù)的序列號,并將待處理數(shù)據(jù)寫入序列號所在槽的下一個空閑槽;RingBuffer將當前最新寫入數(shù)據(jù)的序列號加1并公布,然后通知事件監(jiān)聽處理器以進行數(shù)據(jù)的消費和處理。由于Disruptor相對于傳統(tǒng)方式?jīng)]有鎖也就不存在競爭,因此能夠克服處理延遲較高的問題,另外無需CPU頻繁的資源調(diào)度,因此整體的消息處理性能和吞吐量隨著線程數(shù)量的增加而線性提升。經(jīng)過測試對比發(fā)現(xiàn),基于Disruptor的數(shù)據(jù)收發(fā)方法的性能比基于BlockingQueue的收發(fā)方法高出一個數(shù)量級,數(shù)據(jù)處理的吞吐量和延遲指標都遠遠超越了BlockingQueue的收發(fā)方法高出一個數(shù)量級,數(shù)據(jù)處理的吞吐量和延遲指標都遠遠超越了BlockingQueue的收發(fā)方法。
附圖說明
為了更清楚地說明本發(fā)明實施例,下面將對實施例中所需要使用的附圖做簡單的介紹,顯而易見地,下面描述中的附圖僅僅是本發(fā)明的一些實施例,對于本領域普通技術人員來講,在不付出創(chuàng)造性勞動的前提下,還可以根據(jù)這些附圖獲得其他的附圖。
圖1為本發(fā)明實施例提供的一種基于Disruptor的數(shù)據(jù)收發(fā)方法的流程圖;
圖2為本發(fā)明實施例提供的一種基于Disruptor的數(shù)據(jù)收發(fā)的示意圖;
圖3為本發(fā)明實施例提供的另一種基于Disruptor的數(shù)據(jù)收發(fā)方法的流程圖。
具體實施方式
下面將結合本發(fā)明實施例中的附圖,對本發(fā)明實施例中的技術方案進行清楚、完整地描述,顯然,所描述的實施例僅僅是本發(fā)明一部分實施例,而不是全部實施例?;诒景l(fā)明中的實施例,本領域普通技術人員在沒有做出創(chuàng)造性勞動前提下,所獲得的所有其他實施例,都屬于本發(fā)明保護范圍。
本發(fā)明的核心是提供一種基于Disruptor的數(shù)據(jù)收發(fā)方法,用于在數(shù)據(jù)收發(fā)過程中,克服BlockingQueue和ThreadPoolExecutor所帶來的問題。
為了使本技術領域的人員更好地理解本發(fā)明方案,下面結合附圖和具體實施方式對本發(fā)明作進一步的詳細說明。
圖1為本發(fā)明實施例提供的一種基于Disruptor的數(shù)據(jù)收發(fā)方法的流程圖。圖2為本發(fā)明實施例提供的一種基于Disruptor的數(shù)據(jù)收發(fā)的示意圖。如圖1所示,基于Disruptor的數(shù)據(jù)收發(fā)方法,用于數(shù)據(jù)處理系統(tǒng),包括以下步驟:
S10:當接收到上游子系統(tǒng)的待處理數(shù)據(jù)時,事件處理器獲取Disruptor下的RingBuffer的當前最新寫入數(shù)據(jù)的序列號,并將待處理數(shù)據(jù)寫入序列號所在槽的下一個空閑槽。
S11:RingBuffer將當前最新寫入數(shù)據(jù)的序列號加1并公布,然后通知事件監(jiān)聽處理器以進行數(shù)據(jù)的消費和處理。
Disruptor的關鍵特性是無鎖編程,這個是通過單一寫線程的方式實現(xiàn)的,即一塊數(shù)據(jù)在同一時間永遠只有一個線程寫入。通過遵循這個編程原則來避免使用昂貴的同步鎖或CAS操作,這就是為什么Disruptor這么快的原因。Disruptor在的緩存區(qū)域就是RingBuffer。Ring Buffer:如其名,環(huán)形的緩沖區(qū)。這個數(shù)據(jù)結構的主要特點是,數(shù)據(jù)是被寫入到它上面一個個稱為槽的位置,前提是這個槽是空閑的。
在具體實施中,這些槽的數(shù)量是可以允許自己定義和設置的,作為優(yōu)選地實施方式,RingBuffer中的槽的數(shù)量為2n,其中,n為正整數(shù)。所以它可以是幾萬到幾千萬數(shù)量不等的數(shù)據(jù)緩沖規(guī)模。RingBuffer里的每一個數(shù)據(jù)都有一個序列號(sequence number)來索引,在具體實施中,可以設置序列號與槽的位置號相同。RingBuffer維護當前最新放置的元素的序列號,這個序列號一直遞增,(通過求余來得到數(shù)據(jù)在RingBuffer下面的數(shù)組下標)??梢岳斫獾氖牵绻鸕ingBuffer中的槽用完后,則之前被取走數(shù)據(jù)的槽就可以作為空閑槽進入一輪的使用,此時槽的序號會依據(jù)當前待處理的序列號而變化。
例如,RingBuffer維護的最新寫入的數(shù)據(jù)的序列號是18,事件處理器在接收到待處理數(shù)據(jù)后,從RingBuffer可以獲知下一空閑數(shù)據(jù)寫入槽位是19,則生產(chǎn)線程將待處理數(shù)據(jù)寫入到19號槽位。寫入之后,RingBuffer才會將最后寫入數(shù)據(jù)的序列號更新為19并對外公布,并通知事件監(jiān)聽處理器進行消息數(shù)據(jù)的消費和處理。
如圖2所示,該圖顯示的是基于Disruptor的新技術方案,事件處理器在接收到上游子系統(tǒng)提交來的待處理數(shù)據(jù)后,放入了Disruptor中的內(nèi)存存儲結構RingBuffer中,這些待處理數(shù)據(jù)被認為是一個個事件(event),并被Disruptor中已注冊的若干個事件監(jiān)聽處理器(event handler)監(jiān)聽和處理。在此圖中,左邊將待處理數(shù)據(jù)寫入Ring Buffer結構中的箭頭就是“生產(chǎn)者-消費者”模型中的生產(chǎn)者,而右邊的箭頭,即事件監(jiān)聽處理器就是消費者。
本實施例提供的基于Disruptor的數(shù)據(jù)收發(fā)方法,用于數(shù)據(jù)處理系統(tǒng),包括:當接收到上游子系統(tǒng)的待處理數(shù)據(jù)時,事件處理器獲取Disruptor下的RingBuffer的當前最新寫入數(shù)據(jù)的序列號,并將待處理數(shù)據(jù)寫入序列號所在槽的下一個空閑槽;RingBuffer將當前最新寫入數(shù)據(jù)的序列號加1并公布,然后通知事件監(jiān)聽處理器以進行數(shù)據(jù)的消費和處理。由于Disruptor相對于傳統(tǒng)方式?jīng)]有鎖也就不存在競爭,因此能夠克服處理延遲較高的問題,另外無需CPU頻繁的資源調(diào)度,因此整體的消息處理性能和吞吐量隨著線程數(shù)量的增加而線性提升。經(jīng)過測試對比發(fā)現(xiàn),基于Disruptor的數(shù)據(jù)收發(fā)方法的性能比基于BlockingQueue的收發(fā)方法高出一個數(shù)量級,數(shù)據(jù)處理的吞吐量和延遲指標都遠遠超越了BlockingQueue的收發(fā)方法高出一個數(shù)量級,數(shù)據(jù)處理的吞吐量和延遲指標都遠遠超越了BlockingQueue的收發(fā)方法。
在上述實施例的基礎上,事件處理器通過基于Netty的數(shù)據(jù)傳輸協(xié)議接收上游子系統(tǒng)的待處理數(shù)據(jù)。基于Netty(一個基于NIO的、提供異步的、事件驅動的、客戶-服務器端通信編程框架)的數(shù)據(jù)傳輸協(xié)議,連接上游子系統(tǒng)。上游子系統(tǒng)的待處理數(shù)據(jù)正是通過基于Netty的數(shù)據(jù)傳輸協(xié)議被提交到了核心系統(tǒng)。
Disruptor支持兩種生產(chǎn)者類型,SINGLE和MULTI,即單個生產(chǎn)者模式或多個生產(chǎn)者模式。在具體實施中,可以根據(jù)實際情況設置,如圖2所示,配置的是多個生產(chǎn)者模式。
圖3為本發(fā)明實施例提供的另一種基于Disruptor的數(shù)據(jù)收發(fā)方法的流程圖。在上述實施例的基礎上,還包括:
S12:事件監(jiān)聽處理器通過ExecutorService線程池觸發(fā)數(shù)據(jù)的消費和處理。
在基于Netty的數(shù)據(jù)傳輸協(xié)議中,可以配置事件監(jiān)聽處理器和ExecutorService線程池。這里的事件監(jiān)聽處理器就是消費者(Consumer),可以是一個也可以是多個,它們是通過ExecutorService提供的線程來觸發(fā)消息事件處理的。正是因為有了RingBuffer這一優(yōu)越的數(shù)據(jù)結構作為基礎,配合Disruptor中以序列號(sequence number)來索引這一核心設計要素,使得消費者線程避免了昂貴的同步鎖就可以高效地消費和處理待處理數(shù)據(jù)。
以上對本發(fā)明所提供的基于Disruptor的數(shù)據(jù)收發(fā)方法進行了詳細介紹。說明書中各個實施例采用遞進的方式描述,每個實施例重點說明的都是與其他實施例的不同之處,各個實施例之間相同相似部分互相參見即可。對于實施例公開的裝置而言,由于其與實施例公開的方法相對應,所以描述的比較簡單,相關之處參見方法部分說明即可。應當指出,對于本技術領域的普通技術人員來說,在不脫離本發(fā)明原理的前提下,還可以對本發(fā)明進行若干改進和修飾,這些改進和修飾也落入本發(fā)明權利要求的保護范圍內(nèi)。