一種分散式框架設計(四)
我們設計的分散式系統,在正常工作時呈現出網狀。服務有層次性,客戶的請求會逐步經歷各層服務進行處理,當遍歷完所有服務後才會完成一次請求。每層服務會有若干臺機器,上游節點的機器可以把輸出結果傳遞到下游節點的任意一臺機器上。
當服務所依賴的資料需要更新時,我們需要做好同步工作,並保證在資料更新過程中服務是可用的。這兒介紹兩類更新的操作方式,它們都需要用到zookeeper來實現。
第一類更新只侷限於一個服務的所有機器。我們需要給它們的更新設定一個順序,避免出現該服務所有機器同時更新這種極端情況。Zookeeper鼓勵使用非同步的api進行程式設計,在實現過程中至少有兩種方式來實現這種分散式鎖。第一種是試圖去建立一個既定的結點,如果成功則表示鎖已經拿到,可以開始更新,否則建立觀察點,等待別的機器完成更新後釋放這個鎖(當然仍然可能拿不到);第二種則去建立一個順序節點(sequence),zookeeper能保證建立節點的唯一性,然後服務只需要監控順序在自己之前的節點是否完成了更新(釋放鎖)。當資料量不大時,兩種實現方式的效能應該差別不大,資料量大時推薦使用第二種方式,因為它可以降低通知時產生的網路流量。第一種方式在搶鎖過程中,網路更快的機器更容易搶到,第二種方式是基於排隊機制的。雖然邏輯簡單,但實際程式設計過程中還是會比較麻煩,需要考慮網路傳輸等問題等。
第二類更新是多個服務中有資料依賴的情況。比如服務A和B,它們均有兩臺機器a1, a2, b1, b2。初始時的資料時間戳相同,即服務A的資料是da_t1, 服務B的資料是db_t1。如果我們有了新的資料da_t2和db_t2,我們只允許首先同時更新A和B的其中一臺機器,如a1, b1;這是更新資料後的伺服器也只會把自己的下游資料傳送到已經更新資料的下游伺服器中去,即由原先的a1和a2都可以把下游資料傳送給b1和b2的任意一臺,現在a1只能給b1,a2只能給b2。直到a2, b2均更新為新資料的時候,才能恢復原先的傳輸方式。具體的實施方式是首先我們需要知道整個資料更新的總伺服器的情況, 以資料的名來命名(index),如下: /data/index/A/a1, /data/index/A/a2, /data/index/B/b1,/data/index/B/b2, 一旦時間戳為t2的資料包都準備好了,那麼修改節點/data/index的值為t2(可以一級一級的更新,即/data/index/A, /data/index/B的時間戳都修改為t2後,再修改/data/index),並且選取每類服務的若干機器開始更新,即增加/updating/index/A/a1, /updating/index/B/b1,並賦值為t2。每臺伺服器會監控自己所屬的結點,即a1會監控/updating/index/A/a1,一旦發現該節點出現,就開始進行資料更新,更新完成後會刪除自己的所屬節點。監控服務一旦發現/updating/index/A/a1, /updating/index/B/b1均被刪除了,就會重新賦值/updating/index/A/a2,/updating/index/B/b2。當時間戳為t2的所有資料均完成更新後,對/updated/index進行賦值為t2。但是在實際程式設計過程中,完全按照上面的描述進行會非常的麻煩,所以我們還是進行了簡化,但其邏輯還是得以保證。
至此,對於我設計的分散式框架系統已經介紹完畢。