Rsync 原理

想起以前做項目,用到了Rsync check 文件內(nèi)容,未免以后忘記,現(xiàn)在整理下 大致邏輯

背景:

? ? ? ?我們新建一個文件,上傳,再改動一點點東西,通用辦法就是,把改動后的文件,上傳覆蓋以前的文件,這樣不會錯,但是有個問題,如果這個文件很大,那么整個上傳就會消耗大量的時間和流量,哪怕我們只是編輯了一個標點符號。

解決方案:

? ? ? ?那么有沒有什么辦法,我只上傳編輯的部分,那就萬事大吉了,但是沒有編輯的部分,我怎么告訴server 呢,我可以告訴server ,我沒有改變的部分的 offset ,比如: 0-121 byte,180- 300byte,編輯的部分我上傳data,那么最后的結(jié)果是什么呢:

0-121byte(location),122-179byte(data),180-300 byte.

?????那么,我怎么找出編輯的部分呢,大致方案如下:

? ? 1. 我將原內(nèi)容分割成若干部分(具體每部分多大,根據(jù)文件大小確定),每部分通過算法,得到兩個值,sha -> sum1,md5 ->sum2?

? ? 2. 我將編輯后的文件,按照同樣大小,分割,依次對比,如果發(fā)現(xiàn)sum1 和 sum2 都一樣,那么我們認為這部分是以前的內(nèi)容,記錄下來

? ? 3. 遇到sum1 不一致,或者sum1一致,sum2 不一致的內(nèi)容(這就是為什么要通過兩個算法去校驗,sum2 準確,但是消耗性能,sum1 性能消耗較低,但是不準確),那么我們往后移動一個byte,這一個byte 作為新增的內(nèi)容,記錄下位置,接著從移動過后的位置對比

????4. 一個字節(jié)一個字節(jié)的添加太麻煩,還有如果重用的部分是連續(xù)的,那么我們可以添加邏輯把連續(xù)新增的字節(jié)或者連續(xù)重用的字節(jié)連起來,最后上傳的時候,再上傳連起來的部分的offset 和data

? ? 大致的邏輯就是這樣,但是有個問題:

? ? 原內(nèi)容:[(sum1,sum2),(sum1,sum2),(sum1,sum2).......]

? ? 我們計算編輯后的文件的時候,拿到sum1 和sum2 ,怎么去對比呢,要知道,上面的數(shù)組是相當龐大的,你要挨個去對比,我的天,性能災難,得不償失。

? ? 有什么辦法呢,如果能想key ,value 這樣挨個對應起來就好了,這樣,直接找key,看value 是否有值。

? ??原內(nèi)容:[{sum1:{sum2:xxxxx,location :123-456}}.......]

? ? 但是,這樣有新的問題:

? ? ? ? ? ? 1. sum1 有可能碰撞(不精確)

? ? ? ? ? ? 2. sum1 還是很長,key value 都很長,這樣的性能我們是無法接受的

? ? 如果有什么辦法,能夠?qū)um1 或者sum2 編程一個數(shù)字或者簡單的字符就好了。

? ? 網(wǎng)上找找,果然有,將可以通過一個算法將sum1 變成一個 數(shù)字:

? ? ? ? ? ? ? ? f(sum1) -> 10233

? ? 我們再構(gòu)建一個hashtable 樣子, 表的樣子是什么呢

? ? hashTable[10233] = i, i 表示在原文件中的第幾端,至于其他的都設置成-1,最后結(jié)果

? ? hashTable[0] = -1,....hashTable[10233] = 0,......

? ? 我們拿到編輯后的文件段的sum1, 通過同樣的運算, 獲得的值也是 10233, 那么我們拿這個10233 反過來找hashTable, 發(fā)現(xiàn)value 不是-1, 恭喜你可能找到了,這時再對比下sum2,這樣就能最終確定了,這樣是不是性能提高了很多

? ? 但是還有一個問題,不同內(nèi)容的sum1 可能一樣啊,這咋整,也就是,可能第57 段和第89段的sum1都是10233,那么結(jié)果就是,后面的把前面的覆蓋,結(jié)果就是 hashTabel[10233] = 89

? ? 這咋整?

? ? 我們想如果能記錄后一段,也就是在覆蓋前一段的時候能夠把前一段的location 記錄下來就好了,ok,那么我們新定義一個變量chain,通常情況下,chain值為-1,只有發(fā)現(xiàn)hashTable[10233]有值時,我們把后一個位置的chain 設置成前一個位置的location,這樣是不是就不怕覆蓋了,結(jié)果就是,假設第0,57,89 的結(jié)果都是10233,那么:

hashTable[10233] = 89, data[89].chain = 57, data[57].chain = 0

代碼如下:

for I in 0..<count {

? ? ? ? ? ? ? ? let sumData = file.sums[I] ? ? ? ?

?????????? ? ? ?let t =self.getHashEntry( sum1: sumData.sum1,true)

? ? ? ? ? ? ? ? let subsum = file.sums[i]

? ? ? ? ? ? ? ? subsum.chain=hashTable[Int(t)]

? ? ? ? ? ? ? ? self.hashTable[Int(t)] = i

? ? ? ? ? ? }

perfect!

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 一、為什么要用rsync+sersync架構(gòu)? 1、sersync是基于inotify開發(fā)的,類似于inotify...
    SkTj閱讀 1,918評論 2 14
  • 在C語言中,五種基本數(shù)據(jù)類型存儲空間長度的排列順序是: A)char B)char=int<=float C)ch...
    夏天再來閱讀 3,993評論 0 2
  • 基礎命令 主要的命令和快捷鍵 Linux系統(tǒng)命令由三部分組成:cmd + [options]+[operation...
    485b1aca799e閱讀 1,204評論 0 0
  • 一. Java基礎部分.................................................
    wy_sure閱讀 3,995評論 0 11
  • 前天下班路上,在一個上面有多車道立交橋的大型十字路口,一堆堆的人待在安全線內(nèi)等綠燈。這時,一個三十歲左右的男子,專...
    楊曉木閱讀 264評論 0 4

友情鏈接更多精彩內(nèi)容