有很多軟體在沒有接入網路的情況下也可以運行,等到有網路時,會進行資料同步。這樣在多個用戶端間可以無縫所有。
典型代表:有道雲筆記、挖財記賬本
目前,我使用php開發一款軟體的服務端,軟體提供網頁版和用戶端。在離線狀態下,用戶端主要功能也是可以使用的。
現在採用的方案是:
用C語言寫了一個php的擴充,用於產生唯一int64值。
需要同步的資料表,都添加了一個欄位modify_num,存放唯一int64值,對資料記錄進行增刪改時,都改變modify_num。
用戶端定時執行同步操作,每次同步包含2個原子操作:先是用戶端給服務端自己最大的modify_num,服務端把大於該modify_num的資料都返回給用戶端,簡稱為update;然後用戶端處理完資料後,把用戶端需要進行增刪改的資料發送給服務端,服務端進行處理,簡稱為commit。
補充:
1.為什麼modify_num不直接使用時間戳,而是唯一數值:
我們沒有直接採用時間戳記是有原因的:操作時間間隔太短的時候,產生的時間戳記會是相同的數值。如果不唯一會有這樣的情況發生,在update時服務端返回了多條modify_num相同的資料給用戶端,用戶端每處理一條就修改自己的最大modify_num,萬一用戶端以為外因崩潰,多條資料沒有處理完,下次啟動時發送的最大modify_num給服務端,那麼服務端返回的是大於這個值的資料,意味著那幾條因為崩潰沒有處理的資料都沒有拿到。採用唯一數值就是為了避免這種情況發生。
2.關於衝突處理:
畢竟我們面對的是普通使用者,不是程式員,不會像版本管理工具一樣,有合并衝突的功能,衝突我們有自己的一套簡單機制。基本原則是以modify_num大的優先,以最後操作優先。
大家有沒有更好的方案或者有什麼想法,都可以說說
回複內容:
有很多軟體在沒有接入網路的情況下也可以運行,等到有網路時,會進行資料同步。這樣在多個用戶端間可以無縫所有。
典型代表:有道雲筆記、挖財記賬本
目前,我使用php開發一款軟體的服務端,軟體提供網頁版和用戶端。在離線狀態下,用戶端主要功能也是可以使用的。
現在採用的方案是:
用C語言寫了一個php的擴充,用於產生唯一int64值。
需要同步的資料表,都添加了一個欄位modify_num,存放唯一int64值,對資料記錄進行增刪改時,都改變modify_num。
用戶端定時執行同步操作,每次同步包含2個原子操作:先是用戶端給服務端自己最大的modify_num,服務端把大於該modify_num的資料都返回給用戶端,簡稱為update;然後用戶端處理完資料後,把用戶端需要進行增刪改的資料發送給服務端,服務端進行處理,簡稱為commit。
補充:
1.為什麼modify_num不直接使用時間戳,而是唯一數值:
我們沒有直接採用時間戳記是有原因的:操作時間間隔太短的時候,產生的時間戳記會是相同的數值。如果不唯一會有這樣的情況發生,在update時服務端返回了多條modify_num相同的資料給用戶端,用戶端每處理一條就修改自己的最大modify_num,萬一用戶端以為外因崩潰,多條資料沒有處理完,下次啟動時發送的最大modify_num給服務端,那麼服務端返回的是大於這個值的資料,意味著那幾條因為崩潰沒有處理的資料都沒有拿到。採用唯一數值就是為了避免這種情況發生。
2.關於衝突處理:
畢竟我們面對的是普通使用者,不是程式員,不會像版本管理工具一樣,有合并衝突的功能,衝突我們有自己的一套簡單機制。基本原則是以modify_num大的優先,以最後操作優先。
大家有沒有更好的方案或者有什麼想法,都可以說說
modify_num乾脆改成last_modify比較直觀,內容就是最後一次修改時間戳記,這樣同步的時候帶上上次同步完的時間戳記,伺服器把上次同步之後所有更改發回。
兩邊都維護了一個num,衝突解決如何處理?
如果最初版本值為0,在網頁端和離線用戶端編輯,
同步時,伺服器端和用戶端的版本值都為1;
這就是涉及到衝突問題的解決,你說用戶端先把大於
1的值更新,這時候伺服器的值也是1,但是內容是變化了的;
可以考慮使用類似資料庫的redo日誌;
伺服器和用戶端資料修改前都記錄日誌(含精確的時間戳記);
在用戶端連網後,先將用戶端離線期間的日誌發送到伺服器端,
伺服器端按時間點插入日誌(用戶端服務端日誌合并),redo日誌;
然後,將資料同步到用戶端;
應該參考git軟體內部的實現,有衝突的時候分為可以自動合并和不可以自動合并
merge對於普通使用者門檻太高 讓使用者選擇一個版本基本就夠了 其實最簡單的方法就是讓使用者接受開機自啟動 不知不覺完成同步,。,