數據同步算法研究


1、引言
 基於LAN或WAN的網絡應用之間進行數據傳輸或者同步非常普遍,比如遠程數據鏡像、備份、複製、同步,數據下載、上傳、共享等等,最爲簡單的做法自然就是對數據進行完全複製。然而,數據在網絡上來回被複制多次後就會存在大量副本,很多情形下這些文件副本之間僅有很小的差異,很可能是從同一個文件版本演化而來。如果對文件進行完全複製,在文件較大的情況下,會佔用大量網絡帶寬,同步時間也會較長。目前,廣域網WAN的帶寬與訪問延遲仍然是急需解決的問題,完全複製使得很多網絡應用無法提供良好的服務質量,比如分佈式文件系統(DFS)、雲存儲(Cloud Storage)。Rsync與RDC(Remote Differential Compression)是兩種最爲常見的數據同步算法,它們僅傳輸差異數據,從而節省網絡帶寬並提高效率。本文基於這兩種算法思想並藉助重複數據刪除(De-duplication)技術,對數據同步算法進行深入研究與分析,並研發了原型系統。首先介紹rsync與RDC算法,然後詳細描述算法設計與相應的數據結構,並重點分析文件分塊、差異編碼、文件同步算法,最後簡介推拉兩種應用模式。

2、相關工作
 Rsync是類Unix環境下的一個高效的遠程文件複製(同步)工具,它通過著名的Rsync算法來優化流程,減少了數據通信量並提高文件傳輸效率。假設現在有兩臺計算機Alpha和Beta ,計算機Alpha能夠訪問A文件,計算機Beta能夠訪問B文件,文件A和B非常相似,計算機Alpha和Beta通過低速網絡互聯。它的大致流程如下(詳細過程請參考Rsync作者Andrew Tridgell的tech_report.ps):
 1、Beta將文件B分割成連續不重疊的固定大小數據塊S,最後一個數據塊上可能會小於S字節;
 2、Beta對於每一個數據塊,計算出兩個校驗值,一個32位的弱滾動校驗和一個128位的MD4校驗;
 3、Beta將校驗值發送給Alpha;
 4、Alpha通過搜索文件A的所有大小爲S的數據塊(偏移量可以任意,不一定非要是S的倍數),來尋找與文件B的某一塊有着相同的弱校驗碼和強校驗碼的數據塊。這主要由滾動校驗Rolling checksum快速完成;
 5、Alpha給Beta發送重構A文件的指令,每一條指令是一個文件B數據塊引用(匹配)或者是文件A數據塊(未匹配)。
  Rsync是一個非常優秀的工具,但它仍然存在一些不足之處。
 1、Rolling checksum雖然可以節省大量checksum校驗計算量,也對checksum搜索作了優化,但多出一倍以上的hash查找,這個消耗不小;
 2、Rsync算法中,Alpha和Beta計算量是不對等的,Alpha計算量非常大,而Bete計算量非常小。通常Alpha是服務器,因此壓力較大;
 3、Rsync中數據塊大小是固定的,對數據變化的適應能力有限。
 RDC算法的典型代表是微軟DFS中的DFSR(Distributed File System Replication),它與Rsync不同之處在於採用一致的分塊規則對複製的源文件和目標文件進行切分。因此,RDC對於源端和目標端的計算量是對等的。RDC和RSync算法在設重點上有所不同,Rsync追求更高的重複數據發現而不惜計算量;RDC在兩者之間作了一個折衷,目標是以少量的計算快速發現數據差異,當然重複數據發現不及Rsync。另外,Rsync是定長分塊策略,而RDC是變長分塊策略。

3、重複數據刪除技術
 De-duplication,即重複數據刪除,它是一種非常新的且流行度很高的存儲技術,可以大大減少數據的數量。重複數據刪除技術,通過數據集中重複的數據,從而消除冗餘數據。藉助dedup技術,可以提高存儲系統的效率,有效節約成本、減少傳輸過程中的網絡帶寬。同時它也是一種綠色存儲技術,能有效降低能耗。
 Dedupe按照消重的粒度可以分爲文件級和數據塊級。文件級的dedup技術也稱爲單一實例存儲(SIS, Single Instance Store),數據塊級的重複數據刪除,其消重粒度更小,可以達到4-24KB之間。顯然,數據塊級的可以提供更高的數據消重率,因此目前主流的 dedup產品都是數據塊級的。將文件都分割成數據塊(定長或變長的數據塊),採用MD5或SHA1等Hash算法 (可以同時使用兩種或以上hash算法或CRC校驗等,以獲得非常小概率的數據碰撞發生)爲數據塊計算指紋(FP, Fingerprint)。具有相同FP指紋的數據塊即可認爲是相同的數據塊,存儲系統中僅需要保留一份。這樣,一個物理文件在存儲系統就對應一個邏輯表示,由一組FP組成的元數據。當進行讀取文件時,先讀取邏輯文件,然後根據FP序列,從存儲系統中取出相應數據塊,還原物理文件副本。
 Dedupe技術目前主要應用於數據備份,因此對數據進行多次備份後,存在大量重複數據,非常適合這種技術。事實上,dedupe技術可以用於很多場合,包括在線數據、近線數據、離線數據存儲系統,甚至可以在文件系統、卷管理器、NAS、SAN中實施。也可以用於網絡數據傳輸,當然也可以應用於數據打包技術。Dedupe技術可以幫助衆多應用降低數據存儲量,節省網絡帶寬,提高存儲效率、減小備份窗口,綠色節能。

4、數據同步算法
 如Rsync假設現在有兩臺計算機Alpha和Beta ,計算機Alpha能夠訪問A文件,計算機Beta能夠訪問B文件,文件A和B非常相似,計算機Alpha和Beta通過低速網絡互聯。基於dedupe技術的數據同步算法大致流程與Rsync相似,簡單描述如下:
 1、Beta採用數據切分算法,如FSP(fixed-size partition)、CDC(content-defined chuking),將文件B分割成大小相等或不等的數據塊;
 2、Beta對於每一個數據塊,計算一個類似rsync弱校驗值和md5強校驗值,並記錄數據塊長度len和在文件B中的偏移量offset;
 3、Beta將這將數據塊信息發送給Alpha;
 4、Alpha採用同樣的數據塊切分技術將文件A切成大小相等或不等的數據塊,並與Beta發過來的數據信息進行搜索匹配,生成差異編碼信息;
 5、Alpha將差異編碼信息發送給Beta,並同時發送重構文件A的指令;
 6、Beta根據差異編碼信息和文件B重構文件A。
 上面算法描述中,有幾個關鍵問題需要解決,即文件切分、切分數據塊信息描述、差異編碼、差異編碼信息描述、文件同步。文件切分、差異編碼、文件同步將在後續部分介紹,這裏對切分數據塊信息描述和差異編碼信息描述作說明。
 切分數據塊信息的數據文件佈局由文件頭(chunk_file_header)和數據塊描述(chunk_block_entry)實體集組成,具體定義如下。其中,文件頭定義了文件B的數據塊大小、數據塊總數。文件頭後緊隨一組數據塊描述實體,每個實體代表一個數據塊,定義了塊長度、塊在文件B中的偏移、弱校驗值和強md5校驗值。 
view plaincopy to clipboardprint?
/* define chunk file header and block entry */ 
typedef struct _chunk_file_header {  
        uint32_t block_sz;  
        uint32_t block_nr;  
} chunk_file_header;  
#define CHUNK_FILE_HEADER_SZ    (sizeof(chunk_file_header))  
typedef struct _chunk_block_entry {  
        uint64_t offset;  
        uint32_t len;  
        uint8_t  md5[16 + 1];  
        uint8_t  csum[10 + 1];  
} chunk_block_entry;  
#define CHUNK_BLOCK_ENTRY_SZ    (sizeof(chunk_block_entry)) 
/* define chunk file header and block entry */
typedef struct _chunk_file_header {
        uint32_t block_sz;
        uint32_t block_nr;
} chunk_file_header;
#define CHUNK_FILE_HEADER_SZ    (sizeof(chunk_file_header))
typedef struct _chunk_block_entry {
        uint64_t offset;
        uint32_t len;
        uint8_t  md5[16 + 1];
        uint8_t  csum[10 + 1];
} chunk_block_entry;
#define CHUNK_BLOCK_ENTRY_SZ    (sizeof(chunk_block_entry))
 差異編碼信息的數據文件佈局同樣由文件頭(delta_file_header)和數據塊描述實體(delta_block_entry)集組成,如下所定義。其中,文件頭定義了文件A的數據塊總數、最後一個數據的長度和偏移。文件頭後緊隨一組數據塊描述實體,每個實體代表一個數據塊,定義了數據塊長度、偏移以及數據塊位置指示。如果embeded爲1,則表示數據塊位於差異編碼文件中offset處,數據緊隨該實體後;如果embeded爲0,則表示數據塊位於文件B中offset處。最後數據塊存儲於差異編碼文件尾部,長度和偏移由頭部指示。
view plaincopy to clipboardprint?
/* define delta file header and block entry */ 
typedef struct _delta_file_header {  
        uint32_t block_nr;  
        uint32_t last_block_sz;  
        uint64_t last_block_offset;  /* offset in delta file */ 
} delta_file_header;  
#define DELTA_FILE_HEADER_SZ    (sizeof(delta_file_header))  
typedef struct _delta_block_entry {  
        uint64_t offset;  
        uint32_t len;  
        uint8_t  embeded; /* 1, block in delta file; 0, block in source file. */ 
} delta_block_entry;  
#define DELTA_BLOCK_ENTRY_SZ    (sizeof(delta_block_entry)) 
/* define delta file header and block entry */
typedef struct _delta_file_header {
        uint32_t block_nr;
        uint32_t last_block_sz;
        uint64_t last_block_offset;  /* offset in delta file */
} delta_file_header;
#define DELTA_FILE_HEADER_SZ    (sizeof(delta_file_header))
typedef struct _delta_block_entry {
        uint64_t offset;
        uint32_t len;
        uint8_t  embeded; /* 1, block in delta file; 0, block in source file. */
} delta_block_entry;
#define DELTA_BLOCK_ENTRY_SZ    (sizeof(delta_block_entry))
 從實時性能方面考慮,數據塊信息和差異編碼信息並不一定要寫入文件,可以存在於Cache中,但數據佈局與上面描述相同。

5、文件切分
 Dedupe技術中,數據分塊算法主要有三種,即定長切分(fixed-size partition)、CDC切分(content-defined chunking)和滑動塊(sliding
block)切分。定長分塊算法採用預先定義好的塊大小對文件進行切分,並進行弱校驗值和md5強校驗值。弱校驗值主要是爲了提升差異編碼的性能,先計算弱校驗值並進行hash查找,如果發現則計算md5強校驗值並作進一步hash查找。由於弱校驗值計算量要比md5小很多,因此可以有效提高編碼性能。定長分塊算法的優點是簡單、性能高,但它對數據插入和刪除非常敏感,處理十分低效,不能根據內容變化作調整和優化。
 CDC算法是一種變長分塊算法,它應用數據指紋(如Rabin指紋)將文件分割成長度大小不等的分塊策略。與定長分塊算法不同,它是基於文件內容進行數據塊切分的,因此數據塊大小是可變化的。算法執行過程中,CDC使用一個固定大小(如48字節)的滑動窗口對文件數據計算數據指紋。如果指紋滿足某個條件,如當它的值模特定的整數等於預先設定的數時,則把窗口位置作爲塊的邊界。CDC算法可能會出現病態現象,即指紋條件不能滿足,塊邊界不能確定,導致數據塊過大。實現中可以對數據塊的大小進行限定,設定上下限,解決這種問題。CDC算法對文件內容變化不敏感,插入或刪除數據只會影響到檢少的數據塊,其餘數據塊不受影響。CDC算法也是有缺陷的,數據塊大小的確定比較困難,粒度太細則開銷太大,粒度過粗則dedup效果不佳。如何兩者之間權衡折衷,這是一個難點。
 滑動塊算法結合了定長切分和CDC切分的優點,塊大小固定。它對定長數據塊先計算弱校驗值,如果匹配則再計算md5強校驗值,兩者都匹配則認爲是一個數據塊邊界。該數據塊前面的數據碎片也是一個數據塊,它是不定長的。如果滑動窗口移過一個塊大小的距離仍無法匹配,則也認定爲一個數據塊邊界。滑動塊算法對插入和刪除問題處理非常高效,並且能夠檢測到比CDC更多的冗餘數據,它的不足是容易產生數據碎片。

6、差異編碼
 差異編碼的基礎是文件B數據分塊信息和文件A,它首先對文件A進行對等數據分塊(滑動塊算法除外,它對文件B的切分是定長算法,而對文件A是滑動塊算法),然後匹配文件B數據分塊信息。如果數據塊匹配,則用數據塊索引表示,達到重複數據刪除效果。否則,則將對應的文件A數據塊寫入差異編碼文件中。數據塊匹配算法方面,定長切分和CDC切分是基本相同,文件A採用和文件B對等的切分算法進行數據塊切分。滑動塊算法與其他兩種算法不同,它與rsync類似,它對文件B的切分是定長算法,而對文件A的切分是滑動塊算法。因此,這種算法切分是不對等的。然後根據文件B構造hashtable,通過hash查找進行匹配,並按照差異編碼數據佈局構造相應數據文件。

7、文件同步
 Beta得到差異編碼文件delta,再結合已有的文件B,即可以將文件B同步成文件A的副本。同步算法遍歷delta文件,讀取每一個數據塊描述實體,根據embeded標誌分別從delta和文件B中讀取相應的數據塊,重新構造出文件A。

8、PULL與PUSH模式
 數據同步有PULL和PUSH兩種應用模式,PULL是將遠程數據同步到本地,而PUSH是將本地數據同步到遠程。對應到同步算法,主要區別在於數據分塊和差異編碼位置不同。PULL和PUSH同步模式步驟分別如下所述。
 PULL同步模式流程:
 1、本地對文件A進行數據切分,生成數據塊描述文件chunk;
 2、上傳chunk文件至遠程服務器;
 3、遠程服務器對文件B進行差異編碼,生成差異編碼文件delta;
 4、下載delta文件至本地;
 5、本地同步文件A至文件B,相當於下載文件B到本地文件A。


 PUSH同步模式流程:
 1、遠程服務器對文件B進行數據切分,生成數據塊描述文件chunk;
 2、下載chunk文件至本地;
 3、本地對文件A進行差異編碼,生成差異編碼文件delta;
 4、上傳delta文件至遠程服務器;
 5、遠程同步文件B到A,相當於上傳文件A到遠程文件B。


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/liuben/archive/2010/08/06/5793706.aspx

發佈了35 篇原創文章 · 獲贊 0 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章