5

我正在重構一個分析系統,該系統將進行大量計算,並且我需要關於可能的體系結構設計的一些想法來解決我面臨的數據一致性問題。分佈式分析系統上數據一致性的體系結構設計

當前的架構

我有一個隊列爲基礎的系統,在不同的請求應用程序創建最終由工人使用的消息。

每個「請求應用」分解大的計算成小塊將由工人被髮送到隊列和處理。

當所有作品完成時,原始「請求應用程序」將合併結果。

此外,工人爲了處理請求消耗從集中式數據庫(SQL Server)的信息(重要:工人不改變數據庫的任何數據,只有使用它)。

Current Architecture

問題

確定。到現在爲止還挺好。當我們包含更新數據庫信息的Web服務時,會出現問題。這可能隨時發生,但每個來自同一個「請求應用程序」的「大型計算」在數據庫中看到相同的數據是至關重要的。

例如:

  1. 應用生成消息A1和A2,將其發送到隊列
  2. 工人W1用於處理拾取消息A1。
  3. Web服務器更新數據庫,從狀態S0更改爲S1
  4. 工人W2拿起消息A2進行處理

我只是不容使用數據庫的狀態S1有工人W2。爲了使整個計算一致,它應該使用先前的S0狀態。

思考

  1. 一個鎖模式防止Web服務器更改數據庫,同時還有與它有工人消費的信息。

    • 缺點:鎖可能在很長一段時間,由於在計算形式不同的 「請求的應用」 可能會重疊(A1,B1,A2,B2,C1,B3,等)。
  2. 創建數據庫和工作人員(即控制由REQ數據庫緩存應用程序服務器)之間新層

    • 利弊:添加另一層可能會強加顯著開銷(也許? ),而且這是很多工作,因爲我將不得不重寫工人的持久性(很多代碼)。

我未決的第二個解決方案,但它不是很有信心。

任何精彩的想法?我設計錯了,還是錯過了一些東西?

OBS:

  • 這是一個巨大的2層遺留系統(在C#),我們試圖 演變成與作爲最小的努力更具擴展性的解決方案 可能。
  • 每個工作人員可能在不同的服務器上運行。
+1

聽起來非常像地圖/減少我。你爲什麼要自己寫這樣的東西?我只是使用Hadoop。 – duffymo

+0

我忘了提及這是一個巨大的2層遺留系統(使用C#),我們試圖用盡可能少的努力發展成爲一個更具擴展性的解決方案。我相信把一切都變成哈多普將是一項艱鉅的任務。 –

+0

比編寫,調試和維護Hadoop已經做的更多的工作?我承諾在提交之前。 – duffymo

回答

0

謝謝大家的幫助。

因爲我認爲這是問題在其他情況下可能會很平常,所以我想分享我們選擇的解決方案。

更徹底地思考這個問題,我明白它的真正含義。

  • 我需要某種形式的會話控制的每個作業
  • 有進程的高速緩存充當會話控制每個作業

現在計算已經發展到分佈,我只需要改進我的緩存以便分發。

爲了做到這一點,我們選擇使用內存數據庫(哈希值),作爲單獨的服務器部署。 (在這種情況下爲Redis)。

現在,每當我開始工作的時候,我創建了一個ID爲工作,並把它傳遞給他們的信息

當每個工人希望從數據庫中的一些信息,它會:

  1. 查找在Redis的數據(與作業ID)
  2. 如果數據是在Redis的,使用數據
  3. 如果不是,從SQL加載它,並將其保存在Redis的(與作業ID)。

在作業結束時,我清除與作業ID關聯的所有哈希。

1

你可以用你的數據庫版本嗎?

可以說,請求應用程序用ct1標記了計算的開始。現在,這個計算生成的每條消息都會加上相同的時間戳。

而且每次數據庫更新都會在更新時刻標記數據庫狀態。因此,狀態S0在時間t0上,在t1上的狀態S1上等。

現在當工作人員得到消息時,它需要獲得DB狀態,其中更新時間是最大的,小於或等於消息時間。在你的例子中,如果A1和A2用ct1和t1> ct1標記,那麼兩個工作人員將檢索S0而不是S1。

這當然意味着你需要持有好幾個版本在你的數據庫中。如果您知道您的計算必須在一段時間之後完成,您可以在一定時間後清除這些版本。

+0

你有一個好點。我可以準備每個表以允許版本化,但我需要重寫整個模式。您是否知道Sql Server中的任何功能會自動執行該功能,或者至少使其更容易? –

+0

不是。但是,將時間戳記行添加到數據庫模式通常不會太困難。 –

1

我喜歡選項2,特別是如果全套計算所需的數據量不是不合理的大。我假設有一種方法可以關聯(通過id)屬於同一個整體工作的計算嗎?

當一組計算的第一消息進來,那它撿起查詢數據庫和所有必要去做所有的計算數據,並創建一個臨時數據存儲的工人。此數據存儲會是什麼樣子將取決於很多因素(規模,結構等)什麼,但它可能是一個blob /文檔,在關係模式(通過的correlationID隔離)的一組數據,在一個條目企業緩存等

你需要小心當工人1和工人2二者均在同一組計算工作的情況下,因爲只有他們中的一個應該創建數據存儲,都需要在繼續之前等待商店完全填充。

+0

我可以將計算與相同的整體工作關聯起來。我可以生成一個ID並將其設置爲所有計算。但是發現工作所需的所有數據對我來說是一項非常複雜的任務。我正在考慮將新服務器添加到所有工作人員將訪問的體系結構中,而不是數據庫。此服務器將通過作業ID對來自數據庫的結果進行緩存。你怎麼看 ? –

+0

難道你不是回到原來的問題嗎?或者序列中的每個計算只依賴於之前計算的結果? –

+0

每個計算都是相互獨立的,它們只依賴於數據庫中的數據。這個「服務器」將是唯一的,充當所有與數據庫連接的外觀,以便它可以管理每個人在內存中的緩存。雖然不是很有信心。 –