rsync工做機制(翻譯)

如下是rsync系列篇:html

1.rsync(一):基本命令和用法算法

2.rsync(二):inotify+rsync詳細說明和sersyncshell

3.rsync算法原理和工做流程分析緩存

4.rsync技術報告(翻譯)網絡

5.rsync工做機制(翻譯)ide

6.man rsync翻譯(rsync命令中文手冊)post

本篇爲rsync官方推薦文章How Rsync Works的翻譯,主要內容是Rsync術語說明和簡單版的rsync工做原理。本篇沒有通篇都進行翻譯,前言直接跳過了,但爲了文章的完整性,前言部分的原文仍是保留了。性能

本人譯做集合:http://www.cnblogs.com/f-ck-need-u/p/7048359.htmlui

How Rsync Works
A Practical Overview

Foreword

The original Rsync technical report and Andrew Tridgell's Phd thesis (pdf) Are both excellent documents for understanding the theoretical mathematics and some of the mechanics of the rsync algorithm. Unfortunately they are more about the theory than the implementation of the rsync utility (hereafter referred to as Rsync).this

In this document I hope to describe...

  • A non-mathematical overview of the rsync algorithm.
  • How that algorithm is implemented in the rsync utility.
  • The protocol, in general terms, used by the rsync utility.
  • The identifiable roles the rsync processes play.

This document be able to serve as a guide for programmers needing something of an entré into the source code but the primary purpose is to give the reader a foundation from which he may understand

  • Why rsync behaves as it does.
  • The limitations of rsync.
  • Why a requested feature is unsuited to the code-base.

This document describes in general terms the construction and behaviour of Rsync. In some cases details and exceptions that would contribute to specific accuracy have been sacrificed for the sake meeting the broader goals.

Processes and Roles

當咱們討論rsync時,咱們使用了一些特殊的術語來表明不一樣的進程以及它們在任務執行過程當中所扮演的角色。人類爲了更方便、更準確地交流,使用同一種語言是很是重要的;一樣地,在特定的上下文環境中,使用固定的術語來描述相同的事情也是很是重要的。在Rsync郵件列表中,常常會有一些人對role和processes產生疑惑。出於這些緣由,我將定義一些在將來會使用的關於role和process的術語。

client

role

client(客戶端)會啓動同步進程。

server

role

client本地傳輸時,或經過遠程shell、網絡套接字鏈接的對象,它能夠是遠程rsync進程,也能夠表示遠程的系統。

server只是一個通用術語,請不要與daemon相混淆。

 

 

當client和server創建鏈接以後,將使用sender和receiver這兩個role來代替區分它們。

daemon

role and process 

一個等待從client鏈接的rsync進程。在某些特定平臺下,常稱之爲service。

remote shell

role and set of processes 

爲Rsync client和遠程rsync server之間提供鏈接的一個或多個進程。

sender

role and process 

一個會訪問將被同步的源文件的進程。

receiver

role and proces 

當receiver是一個目標系統時將做爲一個role,當receiver是一個更新數據並寫入磁盤的進程時將做爲一個process。

generator

process 

generator進程識別出文件變化的部分並管理文件級的邏輯。

Process Startup

當Rsync client啓動時,將首先和server端創建一個鏈接,這個鏈接的兩端能夠經過管道,也能夠經過網絡套接字進行通訊。

當Rsync和遠程非daemon模式的server經過遠程shell通訊時,進程的啓動方法是fork遠程shell,它會經過此方法在遠程系統上啓動一個Rsync server端進程。Rsync客戶端和服務端都經過遠程shell間的管道進行通訊。此過程當中,rsync進程未涉及到網絡。在這種模式下,服務端的rsync進程的選項是由遠程shell傳遞的。

當rsync與rsync daemon通訊時,它直接使用網絡套接字進行通訊。這是惟一一種能夠稱爲網絡感知的rsync通訊方式。這種模式下,rsync的選項必須經過套接字發送,具體內容下文描述。

在客戶端和服務端通訊最初,雙方都會發送最大的協議版本號給對方,雙方都會使用較小版本的協議來進行傳輸。若是是daemon模式的鏈接,rsync的選項將從客戶端發送到服務端,而後再傳輸exclude列表,從這一刻開始,客戶端和服務端的關係僅與錯誤和日誌消息傳遞有關。(譯者注:即今後時開始,將採用sender和receiver這兩個角色來描述rsync鏈接的兩端)

本地Rsync任務(源和目標都在本地文件系統)的處理方式相似於push。客戶端(譯者注:此時即源文件端)變爲sender,並fork一個server進程以履行receiver角色的職責,而後client/sender與server/receiver之間經過管道進行通訊。

The File List

file list不只包含了路徑名,還包含了拷貝模式、全部者、權限、文件大小、mtime等屬性。若是使用了"--checksum"選項,則還包括文件級的校驗碼。

rsync鏈接創建完成的第一件事是sender建立它的file list,當file list建立完成後,其內的每一項都會傳遞(共享)到receiver端。

當這件事完成後,兩端都會按照相對於基目錄(base directory)的路徑對file list排序(排序算法依賴於傳輸的協議版本號),當排序完成後,之後對全部文件的引用都經過file list中的索引來查找。

當receiver接收到file list後,會fork出generator進程,它和receiver進程一塊兒完成pipeline。

The Pipeline

rsync是高度流水線化的(pipelined)。這意味着進程之間以單方向的方式進行通訊。當file list已經傳輸完畢,pipeline的行爲以下:

generator --> sender --> receiver

generator的輸出結果是sender的輸入,sender的輸出結果是receiver的輸入。它們每一個進程獨立運行,且只有在pipeline被阻塞或等待磁盤IO、CPU資源時才被延遲。

(譯者注:雖然它們是單方向的,但每一個進程在處理完相關工做的那一刻都會當即將數據傳輸給它的接收進程,並開始處理下一個工做,接收進程接收到數據後也開始處理這段數據,因此它們雖然是流水線式的工做方式,但它們是獨立、並行工做的,基本上不會出現延遲和阻塞)

The Generator

generator進程將file list與本地目錄樹進行比較。若是指定了"--delete"選項,則在generator主功能開始前,它將首先識別出不在sender端的本地的文件(譯者注:由於此generator爲receiver端的進程),並在recevier端刪除這些文件。

而後generator將開始它的主要工做,它會從file list中一個文件一個文件地向前處理。每一個文件都會被檢測以肯定它是否須要跳過。若是文件的mtime或大小不一樣,最多見的文件操做模式不會忽略它。若是指定了"--checksum"選項,則會生成文件級別的checksum並作比較。目錄、塊設備和符號連接都不會被忽略。缺失的目錄在目標上也會被建立。

若是文件不被忽略,全部目標路徑下已存在的文件版本將做爲基準文件(basis file)(譯者注:請記住這個詞,它貫穿整個rsync工做機制),這些基準文件將做爲數據匹配源,使得sender端能夠不用發送能匹配上這些數據源的部分(譯者注:從而實現增量傳輸)。爲了實現這種遠程數據匹配,將會爲basis file建立塊校驗碼(block checksum),並放在文件索引號(文件id)以後當即發送給sender端。若是指定了"--whole-file"選項,則對文件列表中的全部文件都將發送空的塊校驗碼,使得rsync強制採用全量傳輸而非增量傳輸。(譯者注:也就是說,generator每計算出一個文件的塊校驗碼集合,就當即發送給sender,而不是將全部文件的塊校驗碼都計算完成後才一次性發送)

每一個文件被分割成的塊的大小以及塊校驗和的大小是根據文件大小計算出來的(譯者注:rsync命令支持手動指定block size)。

The Sender

Sender進程讀取來自generator的數據,每次讀取一個文件的id號以及該文件的塊校驗碼集合(譯者注:或稱爲校驗碼列表)。

對於generator發送的每一個文件,sender會存儲塊校驗碼並生成它們的hash索引以加快查找速度。

而後讀取本地文件,併爲從第一個字節開始的數據塊生成checksum。而後查找generator發送的校驗碼集合,看該checksum是否能匹配集合中的某項,若是沒有匹配項,則無匹配的字節將做爲附加屬性附加在無匹配數據塊上(譯者注:此處,無匹配字節即表示第一個字節,它表示無匹配數據塊的偏移量,標識無匹配數據塊是從哪裏開始的),而後從下一個字節(即第二個字節)開始繼續生成校驗碼並進行比較匹配,直到全部的數據塊都匹配完成。這種實現方式就是所謂的滾動校驗"rolling checksum"。

若是源文件的塊校驗碼能匹配上校驗碼集合中的某項,則認爲該數據塊是匹配塊,而後全部累積下來的非文件數據(譯者注:如數據塊重組指令、文件id等)將隨同receiver端對應文件的匹配數據塊的偏移量和長度一同發送給receiver端(譯者注:例如匹配塊對應的是receiver端此文件的第8個數據塊,則發送偏移量、匹配的塊號和數據塊的長度值,雖然數據塊的大小都是固定的,可是因爲文件分割爲固定大小的數據塊的時候,最後一個數據塊的大小可能小於固定大小的值,所以爲了保證長度徹底匹配,還須要發送數據塊的長度值),而後generator進程將滾動到匹配塊的下一個字節繼續計算校驗碼並比較匹配(譯者注:此處能匹配數據塊,滾動的大小是一個數據塊,對於匹配不上的數據塊,滾動的大小是一個字節)

經過這種方式,即便兩端文件的數據塊順序或偏移量不一樣,也能夠識別出全部能匹配的數據塊。在rsync算法中,這個處理過程是很是核心的。

使用這種方式,sender將發送一些指令給receiver端,這些指令告訴receiver如何將源文件重組爲一個新的目標文件。而且這些指令詳細說明了在重組新目標文件時,全部可從basis file中直接複製的匹配數據塊(固然,前提是它們在receiver端已存在),還包含了全部receiver端不存在的裸數據(注:即純數據)。在每一個文件處理的最後階段,還會發送一個whole-file的校驗碼(譯者注:此爲文件級的校驗碼),以後sender將開始處理下一個文件。

生成滾動校驗碼(rolling checksum)以及從校驗碼集合中搜索是否能匹配的階段須要一個不錯的CPU。在rsync全部的進程中,sender是最消耗CPU的。

The Receiver

receiver將讀取從sender發送過來的數據,並經過其中的文件索引號來識別每一個文件,而後它會打開本地文件(即被稱爲basis file的文件)並建立一個臨時文件

以後receiver將從sender發送過來的數據中讀取無匹配數據塊(即純數據)以及匹配上的數據塊的附加信息。若是讀取的是無匹配數據塊,這些純數據將寫入到臨時文件中,若是收到的是一個匹配記錄,receiver將查找basis file中該數據塊的偏移量,而後拷貝這些匹配的數據塊到臨時文件中。經過這種方式,臨時文件將從頭開始組建直到組建完成。

當臨時文件組建完成,將生成此臨時文件的校驗碼。最後,會將此校驗碼與sender發送過來的校驗碼比較,若是比較發現不能匹配,則刪除臨時文件,並將在第二階段從新組建該文件,若是失敗了兩次,則報告失敗。

在臨時文件最終徹底組建成功後,將設置它的全部者、權限、mtime,而後重命名並替換掉basis file。

在rsync全部的進程中,因爲receiver會從basis file中拷貝數據到臨時文件,因此它是磁盤消耗最高的進程。因爲小文件可能一直處於緩存中,因此能夠減輕磁盤IO,可是對於大文件,緩存可能會隨着generator已經轉移到其餘文件而被沖刷掉,而且sender會引發進一步的延遲。因爲可能從一個文件中隨機讀取數據並寫入到另外一個文件中,若是工做集(working set)比磁盤的緩存大,將可能會發生所謂的seek storm,這會再一次下降性能。

The Daemon

和不少其餘的daemon相似,會爲每一個鏈接都fork一個daemon子進程。在啓動時,它將解析rsyncd.conf文件,以肯定存在哪些模塊,而且設置全局選項。
當已定義好的模塊接收到一個鏈接時,daemon將會fork一個子進程來處理該鏈接。而後該子進程將讀取rsyncd.conf文件並設置被請求模塊的選項,這可能會chroot到模塊路徑,還可能會刪除進程的setuid/setgid。完成上述過程以後,daemon子進程將和普通的rsync server同樣,扮演的角色多是sender也多是receiver。

The Rsync Protocol

一個設計良好的通訊協議會有一系列的特色。

  • 全部要發送的東西明肯定義在數據包中,包括首部,可選的body或數據負載量。
  • 每一個數據包的首部指定了協議類型或指定了命令行。
  • 每一個數據包的長度都是明確的。

除了這些特色以外,協議還應該具備不一樣程度的狀態、數據包之間的獨立性、人類可讀性以及重建斷開鏈接的會話的能力。

rsync的協議不包括上述任何特性。數據經過不間斷的字節流進行傳輸。除了非匹配的數據外,既沒有指定長度說明符,也沒有長度計數器。相反,每一個字節的含義取決於由協議層次定義的上下文環境。

例如,當sender正在發送file list,它僅只是簡單地發送每一個file list中的條目,而且使用一個空字節表示終止整個列表。generator以相同的方式發送文件號以及塊校驗碼集合。

在可靠鏈接中,這種通訊方式能很是好地工做,它比正式的協議工做方式具備更少的數據開銷。但很不幸,這也一樣使得幫助文檔、調試過程變得很是晦澀難懂。每一個版本的協議可能都會有細微的差別,所以只能經過了解確切的協議版原本預知發生了什麼改變。

notes

This document is a work in progress. The author expects that it has some glaring oversights and some portions that may be more confusing than enlightening for some readers. It is hoped that this could evolve into a useful reference.

Specific suggestions for improvement are welcome, as would be a complete rewrite.

相關文章
相關標籤/搜索