基于diff的文件同步算法(上)
1.寫在前面
文件同步的核心問題是新舊版本的對比問題。這里所說的版本是指用于區分文件變更的一種狀態標記,它可以是我們通常所說的版本號,也可以是時間戳,如修改時間。本文介紹一種基于diff的文件同步算法,共分為兩篇,上篇介紹diff算法的服務端實現,下篇介紹diff算法的客戶端實現。
2.算法概述
從客戶端的角度來看,文件同步的本質是本地文件集合與云端文件集合的對比。從實現角度來講,客戶端會保存一份云端文件集合的快照,通過將快照和云端集合對比可以計算出云端文件變更,通過將快照和本地集合對比則可以計算出本地文件變更。對于本地文件的變更,需要將文件提交至云端;對于云端文件的變更,需要將文件同步至本地。對于文件同步在云端和本地都有修改的情況下,就需要進行沖突處理。
如果每個同步周期需要獲取云端文件集合,文件量小還可以接受,文件量一大,對帶寬和服務器壓力都會存在瓶頸,而且很多文件可能根本就沒有變更,這會造成很多無效的對比,浪費計算資源。所以需要一種增量機制,用于增量拉取云端變更的文件。
diff算法是利用修改時間作為增量機制,其核心是每次diff時會記錄下當前diff的時間戳,客戶端下次diff時,帶上上次diff時返回的時間戳(通常將時間戳編碼到cursor中),這樣就能增量獲取到一段時間內的變更記錄了。由于每次diff的變更文件集合可能非常大,所以需要進行分頁操作,有兩個主要的問題需要解決:
- 首次diff問題
- 用時間維度獲取變更記錄時,如(t1, t2]之間的文件變更,由于t1、t2通常是使用秒作為精度,每次分頁diff出的文件記錄時,如果存在閉區間t2時刻文件記錄,則無法判斷t2時刻是否存在更多的記錄。
3.全量同步
首次diff通常發生在客戶端本地快照沒有數據且第一次請求時,這種情況通常指全量同步。服務器在處理全量同步時是希望盡量將當時請求時刻以內的所有文件數據都分頁吐給客戶端。由于時間戳存在增量同步的問題,可以使用文件惟一標識迭代出全量數據。如果記文件的惟一標識為fid,修改時間為mtime,分頁大小為pagesize,SQL查詢具體做法為:
?
select fields from file_meta where fid>last_fid and mtime<=stime sort by fid ASC limit pagesize;其中:
- stime是第一次全量同步時,記錄下當前請求的時間戳,主要是明確一個時間限界內的全量數據,防止在全量同步過程中又出現新的變更;
- last_fid為最近一次查詢結果中最后一條記錄的fid,首次查詢last_fid為0;
- 判斷是否有更多數據通常采用多取一條記錄進行判斷;
- 由于并不知道全量同步過程中是否有新的文件變更,需要進行一次增量同步;
4.增量同步
前面說到在按時間維度進行增量同步時,由于需要分頁,并不知道閉區間內是否有更多文件變更記錄。舉個粟子,當我們查詢出(t1, t2]的文件集合時,如果恰好有幾個文件的修改時間等于t2,而且本次分頁并沒有拉取完。下次diff時會查詢(t3, t4]時間區間內的文件(t3>t2),由于上次并沒有拉取完,即t2時間可能還有更多數據,如果直接查詢(t3, t4]時間區間的文件,那么可能會丟失t2時間的文件記錄。
對于以上情況,當查詢(t1, t2]時間區間內的文件時,針對返回的文件,我們需要對最后一秒的文件進行單獨處理。如果返回的文件的修改時間均是在一秒內,那么稱為單秒增量同步,其它情況稱為正常增量同步。
4.1.正常增量同步
對于正常增量同步雖然所有文件的mtime不是在同一秒內,但需要處理最后一秒問題,就像前面的例子,當分頁未完成時,我們沒辦判斷最后一秒是否還有更多數據,所以一個簡單的做法是從本次查詢的文件記錄中,從最后一個文件開始,移除mtime相同的文件,即把最后一秒的文件留到下次進行查詢。當最后一秒的文件足夠多,比如超過一個分頁時,就會觸發單秒增量同步。正常增量同步查詢SQL表示:
?
select fields from file_meta where mtime>t1 and mtime<=t2 sort by mtime DESC limit pagesize;4.2.單秒增量同步
單秒增量同步是指查詢一秒內的文件記錄,這種查詢比較簡單,如果用SQL表示如下:
?
select fields from file_meta where mtime=xxx sort limit pagesize;5.其它工程問題
在工程實現上還需要注意很多問題,比如主從同步、頻率控制、數據重置等。
5.1.主從同步
對服務器來講,文件數據的存儲量通常都比較大,不可能采用單機就能搞定,一般都會采用分布式進行存儲,對于分布存儲就會存儲主從同步問題。當寫操作完成后,馬上讀取,如果主從同步未完成,并不能讀取出數據。所以在diff的時間滑動窗口中,需要做一定的延遲處理,延遲時間肯定需要大于主從同步的時間。
5.2.頻率控制
對于diff接口,可能會調用的比較頻繁,如果不進行頻率控制,高峰期時可能會造成雪崩效率,diff接口需要有降級和頻控處理。diff接口一般來說是一種后臺行為,并不需要進行實時調用,當客戶端進行增量同步時,如果在一段很短的時間內連續調用,應觸發頻控策略。
5.3.數據重置
由于客戶端會緩存云端數據快照,如果客戶端存在臟數據,將導致同步算法失敗。服務器應該和客戶端約定一種數據重置機制,當服務器端數據升級或出現臟數據時,服務端可以下發數據重置命令,客戶端收到數據重置命令后應該清空本地緩存,重新進行全量同步。
6.總結
diff算法需要處理全量同步和增量同步的情況。全量同步按照文件id維度排序分頁下發;增量同步按照時間維度分頁下發,由于分頁原因以及時間精度問題,不能判斷最后一秒內是否存在更多的數據需要查詢,因為把最后一秒的數據進行單獨查詢。最后就是需要考慮一些工程上的問題,如主從同步、頻率控制、接口降級、數據重置等問題。
作者:AlgoPeek
鏈接:https://www.jianshu.com/p/1d889fb14ca3
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
總結
以上是生活随笔為你收集整理的基于diff的文件同步算法(上)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 组团办信用卡怎么样?团办信用卡有什么好处
- 下一篇: C#的变迁史09 - C# 5.0 之调