2009-09-18 50 views
0

我有一個應用程序,有大約10種類型的對象。每種類型可能會有幾千個對象實例。這些對象列表需要在不同機器上運行的應用程序之間保持同步。如果一個對象被添加,更改或刪除,需要傳播到其他機器。用於在計算機之間同步對象列表的模式(C++中)?

這將是一個星形拓撲結構 - 有一箇中央主站,其餘都是客戶端。

我有一個會話的概念,所以可以存儲有關每個客戶端的數據。

有沒有一個好的設計模式可以遵循這一點?更好的是,有一個(基於模板的?)庫可以處理詢問容器自客戶端X出現以來發生了哪些變化,並使該變量發出?

現在我想每個對象類型的容器都有一個更新計數器。當添加/更改/刪除某些內容時,更新計數器會遞增,並且已更改的對象將使用該值進行標記。每個客戶端在獲取更新時都會保存更新計數器的值。之後它會回來並要求更新計數器值以來的任何更改。最後,刪除被保留爲邏輯刪除記錄(雖然我不確定何時清除它們)。

有一件事情會讓客戶無法知道,但客戶可以來來去去,儘管我猜可能會有超時的概念(如果服務器在5分鐘內沒有聽到客戶的聲音,客戶不在)

這是一個衆所周知的模式?任何其他建議?

+0

您看到的方法的唯一問題是,如果對同一字段有1000個更改,則新客戶端將收到1000個更新而不是1個。 – Toad 2009-09-18 15:02:26

+0

如果對象的只有一個副本更新計數器比客戶端存儲的更新計數器更新。 – DougN 2009-09-18 15:08:17

+1

系統聲音有點像一個顛覆服務器(儘管admitedly簡單得多)...如果你正在尋找靈感,你可以模擬你在該應用程序。 – 2009-09-18 23:57:47

回答

1

如何非常實現同步取決於您的需求。是否需要將更改發送到客戶端,或者只要客戶端使用對象時檢查對象是否是最新的就足夠了?如何使用Proxy pattern?這種模式允許你創建一個你的對象的代理實現,它可以檢查它們是否是最新的,如果它們不是最新的,就更新它們,然後返回結果。我會通過在主對象上擁有lastChanged時間戳和客戶端對象上的lastUpdated時間戳來完成此操作。如果延遲是一個問題,檢查每次調用中對象是否是最新的可能不是一個好主意。考慮有一個單獨的線程,查詢主變更對象並將其標記爲「髒」。這也可以大大減少網絡流量。

您還可以查看Observer patternPublish/Subscribe

+0

延遲可能會是一個問題,所以我不認爲代理模式的工作原理。而且由於會有這麼多的對象(可能是10K),甚至可能有100個客戶端,發佈/訂閱似乎會增加大量的開銷,並且有很多單獨的更新被觸發。 我更多地尋找客戶可以顯示並說'自從我上次來以來發生了什麼變化'並獲得返回數據的批量列表的內容。 – DougN 2009-09-18 20:32:28

0

一個可能很容易實現且效率仍然非常高的選項是將一堆對象視爲不透明blob並使用librsync來同步它們。聽起來像所有的更新流向了一個方向,從主服務器到客戶端,並且可能有一些客戶端上的對象的持久表示 - 文件或其他東西。我假設它是這個答案的其餘部分的文件,儘管可以使用任何字節序列。

它的工作方式是每個客戶端都會生成一個librsync「簽名」,並將其簽名發送給主服務器。簽名大約是blob大小的1%。然後,主服務器將使用librsync來計算該簽名和當前數據之間的增量,並將增量發送給客戶端,客戶端將使用librsync將增量應用於其本地副本。

librsync API很簡單,簽名/增量數據傳輸相對有效。

如果這不是可行的,它可能仍然是有用的,採取更加手冊「基於增量」的方針,以避免做每個對象的版本。每次主人進行更改時,都應該將更改記錄到日記中,記錄完成的內容以及對象。版本控制是在整個數據庫級別完成的,因此實際上版本號會分配給每個日記帳分錄。

當客戶端連接,它應該發送它的整個對象集合的版本,然後服務器可以與客戶端版本和最新的項目之間的期刊的內容作出迴應。如果給定對象上的更新被完全替換對象的內容做了,那麼你可以過濾掉所有,但最新版本的每個對象的優化這個。如果主人也跟蹤哪些版本發送給哪個客戶端,它可以知道何時放棄舊的日記帳條目是安全的。即使不跟蹤,你可以根據一些啓發式(可能只是年齡)還是丟棄舊日誌條目,如果你從客戶端接收其最後的版本比最古老的日記條目年長的連接,那麼你只需要將整個對象集發送給該客戶端。

相關問題