天天看點

Zookeeper場景實踐:(8) 分布式隊列

第二種隊列可以先建立一個/queue,指派為n,表達隊列的大小。然後每個隊列成員加入時,就判斷是否達到隊列要求的大小,如果是可以進行下一步動作,否則繼續等待隊列成員的加入。比較典型的情況是,當一個大的任務可能需要很多的子任務完成才能開始進行。

比如彙總賬單的時候,就必須先将使用者的消費資料,積分資料等都統計完成後才能開始。彙總賬單的程式建立一個隊列/queue,指派為2,然後分别統計消費資料和積分資料的程式當完成任務時就往/queue下建立一個臨時節點。而彙總賬單程式監測到/queue的子節點個數為2時,就可以開始執行任務了。

實際上,我們也可以先建立一個數目為2的子節點。當一個子任務完成的時候,就删除一個子節點,當所有子節點都被删除的時候,主任務就可以開始執行了。這個過程可以形象的了解為拆除屏障。是以這種隊列還有一個專門的詞語描述,叫做屏障(barrier)。

講了那麼多的關于屏障的認識,但是并不打算就去實作它,并且zookeeper的官方文檔也有相關的知識。這次的主要目标是正常的fifo隊列。我将實作隊列的兩個主要操作:push和pop。

1). <code>int push(zhandle_t *zkhandle,const char *path,char *element)</code>

<code>zkhandle</code>為<code>zookeeper_init</code>初始化後的句柄

<code>path</code>為隊列的路徑

<code>element</code>為要壓入隊列的内容

2). <code>int pop(zhandle_t *zkhandle,const char *path,char *element_buffer,int *buffer_len)</code>

<code>element_buffer</code>為要彈出的緩沖區

<code>buffer_len</code>為指向緩沖區的大小的指針

簡單來說,假設隊列的路徑為/queue,<code>push</code>就是就是建立一個臨時有序的/queue/queue-節點。pop就是取出/queue/下序列号最小的節點。

我們知道在c++中stl裡有一個queue的類,實作了push,pop等操作,然而它是非線程安全的,即多個線程同時push/pop的時候可能會出現錯誤。而由于zookeeper保證了建立節點和删除節點的一緻性,是以可以說利用zookeeper實作的隊列是程序安全的。

來看push和pop的具體實作。<code>push</code>的實作很簡單,就是在{path}下建立一個有序的{path}/queue-子節點.

<code>pop</code>的功能則是取出{path}下序号最小的子節點,如果沒有子節點,則傳回-1.

最後,再來看看模拟隊列操作的程式。和其他程式類似,它的選項有

<code>-p</code>:指定隊列的路徑

<code>-m</code>:指定操作是push還是pop

<code>-v</code>:隻在push時有用,用與指定要push的元素的值

<code>-s</code>:指定zookeeper的伺服器的ip:port.

如:

向隊列/queue中壓人一個元素,元素的值為"hello":

将隊列/queue彈出一個元素

最後附上完整的源代碼:

繼續閱讀