rsync算法

最近在學習rsync工具的核心算法,主要參考的是collshell上的一篇文章。

rsync主要解決的是文件的同步問題,比如有A,B兩臺機器,要把A上的一個文件src更新到B上,假如B上已經有一個較舊的版本dest,這時怎么傳輸最省流量。

用過svn等版本工具的都知道,只需要把差異化的部分傳輸過去就夠了,比如src比dest就多了一行內容,那么把這一行傳輸過去就夠了,也就是文件做diff。可是現在有一個問題,src與dest分別在兩臺不同的機器上,而文件要做diff,得同時有兩個文件才行,這就相當于要先把dest傳回給A,這恐怕不是我們想要的。

有什么更好的辦法呢?

可以把文件分塊,比如128字節一個塊,然后這個塊的內容計算一個hash值,dest文件做了這些事情后,把hash信息發送到src處,src也這樣干,然后兩者逐一匹配,不就知道哪一塊不同,然后就可以把差異傳過去了,對吧。

問題來了,如果src文件在某個地方增加了一個字母A,這樣分塊的時候,src計算出來的hash值,整個都錯亂了,會傳輸很多無用的數據,其實我們應該只需要傳輸一個字母A給dest,怎么解決呢?

采取一個滑動窗口的形式,比如分塊是128字節,src先計算第一個塊的hash值,如果在dest發過來的hash信息中找到了,得到這個塊的id,如果沒找到,把窗口向后移動一個字節,繼續計算該block的hash信息,到dest發來的信息中匹配,同上了。

大概流程:

1.dest文件分塊,計算兩個信息,一個弱的校驗hash,一個強的md5hash,帶上塊id,發送到src處。

2.src計算第一個塊的弱hash值,到dest發來的hash信息中查找:

3.如果找到,很好,說明這一塊的內容很有可能在dest中存在,計算塊的md5進行強校驗。

4.如果沒有找到,說明該塊有差異化內容,窗口往后滑動一個字節,計算該塊的弱hash值,即重復步驟2

最后發給dest的信息是這樣的:

?10|tttt|1|2|5|8|ddddd|1

其中數字表示塊id,其他為差異化內容,dest收到這些信息后,自己重組文件,收工。

其最核心的內容為:窗口往后滑動一個字節計算弱hash值的時候,不再是手動計算,而是可以根據前一個窗口的hash信息推算出來,這樣效率要高很多。假設 h(i,j)表示字節i到j的hash信息,那么h(i+1,j+1)可以根據 A[i],h(i,j),A[j+1]計算出來,我采用的是zlib的adler32算法。

寫了個測試代碼:

https://github.com/xiaocc2012/rsync

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 測試環境: rsync-server:192.168.1.132 rsync-client:192.168.1.2...
    lailai900201閱讀 2,384評論 0 10
  • 一、什么是rsync rsync是一款開源,快速,多功能的可實現增量的本地或遠程的數據鏡像同步備份的優秀工具。適用...
    逗比punk閱讀 2,467評論 0 1
  • 簡介:### rsync 是Linux系統下的數據鏡像備份工具,通過rsync 可以將本地的系統數據通過網絡備份到...
    Lisong閱讀 4,683評論 0 4
  • 4層負載均衡和7層負載均衡的區別。A、rsync的安裝;軟件包安裝# yum install rsync 注...
    米開朗基樂閱讀 3,701評論 0 1
  • 其實我的朋友圈還好呀,我不知道那些控訴被自己朋友圈里秀恩愛的虐得如何如何的人,他們的朋友圈到底是什么樣子,或許他們...
    笑丫丫閱讀 306評論 0 2