同步就是將物理內存中dirty的頁寫入到磁盤中,保證磁盤和物理頁之間的內容一致。
觸發同步操作的時機:
1、周期性內核線程,掃描臟頁,根據一定的規則選擇臟頁,將頁寫回到磁盤。
2、如果內核中的臟頁過多,會觸發同步
3、內核中其它組件觸發同步操作(如sync、fsync和fdatasync等函數調用)
傳統的UNIX實現在內核中設有緩沖區高速緩存或頁面高速緩存,大多數磁盤I/O都通過緩沖進行。當將數據寫入文件時,內核通常先將該數據復制到其中一個緩沖區中,如果該緩沖區尚未寫滿,則並不將其排入輸出隊列,而是等待其寫滿或者當內核需要重用該緩沖區以便存放其他磁盤塊數據時,再將該緩沖排入輸出隊列,然后待其到達隊首時,才進行實際的I/O操作。這種輸出方式被稱為延遲寫(delayed write)(Bach [1986]第3章詳細討論了緩沖區高速緩存)。
延遲寫減少了磁盤讀寫次數,但是卻降低了文件內容的更新速度,使得欲寫到文件中的數據在一段時間內並沒有寫到磁盤上。當系統發生故障時,這種延遲可能造成文件更新內容的丟失。為了保證磁盤上實際文件系統與緩沖區高速緩存中內容的一致性,UNIX系統提供了sync、fsync和fdatasync三個函數。
sync函數或者命令:只是將所有修改過的塊緩沖區排入寫隊列,然后就返回,它並不等待實際寫磁盤操作結束。通常稱為update的系統守護進程會周期性地(一般每隔30秒)調用sync函數。這就保證了定期沖洗內核的塊緩沖區。命令sync(1)也調用sync函數。linux默認情況下幾乎所有應用場合都是不會將文件立馬保存入磁盤的,在嵌入式上也是同樣的表現,如果mount時候加上sync選項就可以保證數據立馬寫入,但是這種會造成系統較多的寫入磁盤,磁盤的壽命就不會太長了,如果是需要保存數據,可以顯式調用命令sync來寫入所有文件,或者fsync來保存某個文件。unix系統運行經驗表明,為確保可靠起見,應執行兩遍sync命令,這是因為sync命令完成時,並不保證信息實際寫到了磁盤上,雖然已經執行了一遍這個命令,cp 完之后要執行 sync 命令將緩沖區的內容寫到磁盤中。
fsync函數只對由文件描述符filedes指定的單一文件起作用,並且等待寫磁盤操作結束,然后返回。fsync可用於數據庫這樣的應用程序,這種應用程序需要確保將修改過的塊立即寫到磁盤上。
fdatasync函數類似於fsync,但它只影響文件的數據部分。而除數據外,fsync還會同步更新文件的屬性。
對於提供事務支持的數據庫,在事務提交時,都要確保事務日志(包含該事務所有的修改操作以及一個提交記錄)完全寫到硬盤上,才認定事務提交成功並返回給應用層。
一個簡單的問題:在*nix操作系統上,怎樣保證對文件的更新內容成功持久化到硬盤?
write不夠,需要fsync
1 #include <unistd.h>
2 int fsync(int fd);
1 #incude <sys/mman.h>
2 int msync(void *addr, size_t length, int flags)
msync需要指定同步的地址區間,如此細粒度的控制似乎比fsync更加高效(因為應用程序通常知道自己的臟頁位置),但實際上(Linux)kernel中有着十分高效的數據結構,能夠很快地找出文件的臟頁,使得fsync只會同步文件的修改內容。
fsync的性能問題,與fdatasync
多余的一次IO操作,有多么昂貴呢?根據Wikipedia的數據,當前硬盤驅動的平均尋道時間(Average seek time)大約是3~15ms,7200RPM硬盤的平均旋轉延遲(Average rotational latency)大約為4ms,因此一次IO操作的耗時大約為10ms左右。這個數字意味着什么?下文還會提到。
Posix同樣定義了fdatasync,放寬了同步的語義以提高性能:
1 #include <unistd.h>
2 int fdatasync(int fd);
1.每個log文件固定為10MB大小,從1開始編號,名稱格式為“log.%010d"
2.每次log文件創建時,先寫文件的最后1個page,將log文件擴展為10MB大小
3.向log文件中追加記錄時,由於文件的尺寸不發生變化,使用fdatasync可以大大優化寫log的效率
4.如果一個log文件寫滿了,則新建一個log文件,也只有一次同步metadata的開銷
另外兩個命令:async(IO異步),rsync(遠程同步)。
Rsync 是一個小巧的算法的強大實現。它最基本的功能是高效地鏡像一個文件系統的能力。使用 rsync,可以靈活地選用一組網絡協議,諸如 nfs、smb 或ssh,方便地讓一個文件系統與另一個文件系統保持同步更新。Rsync 的第二個功能,也就是備份系統使用的功能,它可以把已經發生改變或是被刪除的文件的老的版本歸檔。
Rsync 是一個遠程數據同步工具,可通過LAN/WAN快速同步多台主機間的文件。Rsync本來是用以取代rcp的一個工具,它當前由rsync.samba.org維護。Rsync使用所謂的“Rsync演算法”來使本地和遠程兩個主機之間的文件達到同步,這個算法只傳送兩個文件的不同部分,而不是每次都整份傳送,因此速度相當快。運行Rsync server的機器也叫backup server,一個Rsyncserver可同時備份多個client的數據;也可以多個Rsync server備份一個client的數據。
Rsync可以搭配rsh或ssh甚至使用daemon模式。Rsync server會打開一個873的服務通道(port),等待對方Rsync連接。連接時,Rsyncserver會檢查口令是否相符,若通過口令查核,則可以開始進行文件傳輸。第一次連通完成時,會把整份文件傳輸一次,下一次就只傳送二個文件之間不同的部份。
Rsync支持大多數的類Unix系統,無論是Linux、Solaris還是BSD上都經過了良好的測試。此外,它在windows平台下也有相應的版本,比較知名的有cwRsync和Sync2NAS。
Rsync的基本特點如下:
1.可以鏡像保存整個目錄樹和文件系統;
2.可以很容易做到保持原來文件的權限、時間、軟硬鏈接等;
3.無須特殊權限即可安裝;
4.優化的流程,文件傳輸效率高;
5.可以使用rcp、ssh等方式來傳輸文件,當然也可以通過直接的socket連接;
6.支持匿名傳輸。
命令語法
rsync的命令格式可以為以下六種:
rsync [OPTION]… SRC DEST rsync [OPTION]… SRC [USER@]HOST:DEST rsync [OPTION]… [USER@]HOST:SRC DEST rsync [OPTION]… [USER@]HOST::SRC DEST rsync [OPTION]… SRC [USER@]HOST::DEST rsync [OPTION]… rsync://[USER@]HOST[:PORT]/SRC [DEST]
對應於以上六種命令格式,rsync有六種不同的工作模式:
1)拷貝本地文件。當SRC和DES路徑信息都不包含有單個冒號”:”分隔符時就啟動這種工作模式。
2)使用一個遠程shell程序(如rsh、ssh)來實現將本地機器的內容拷貝到遠程機器。當DST路徑地址包含單個冒號”:”分隔符時啟動該模式。
3)使用一個遠程shell程序(如rsh、ssh)來實現將遠程機器的內容拷貝到本地機器。當SRC地址路徑包含單個冒號”:”分隔符時啟動該模式。
4)從遠程rsync服務器中拷貝文件到本地機。當SRC路徑信息包含”::”分隔符時啟動該模式。
5)從本地機器拷貝文件到遠程rsync服務器中。當DST路徑信息包含”::”分隔符時啟動該模式。
6)列遠程機的文件列表。這類似於rsync傳輸,不過只要在命令中省略掉本地機信息即可。