2012-05-21 39 views
0

我正在創建一個Windows服務,它在插入特定USB密鑰時運行。 它所做的很簡單:聯繫FTP服務器,下載某些文件並將它們存儲在(加密的)存檔在USB上。可以使用提供給客戶端的工具以只讀 打開存檔(但這與我的問題無關)。基於事務的歸檔容器

該服務用於保持USB與主服務器同步(非常像Dropbox,但只有下載和同步文件夾位於可移動媒體上)。檔案可以增長到幾千兆字節。大約1GB的文件每週更新約400個用戶的密鑰。

由於整個更新過程對於用戶來說都是透明的,所以當數據被寫入存檔時(即使我提出某種尖叫,華而不實的警告:),他們不可能忽略USB。 請勿插入)。破壞歸檔文件需要全部下載,這意味着已經加載的服務器浪費了很多帶寬。

所以基本上我需要寫入檔案爲成交。如果他們失敗了,只要他們不將容器置於不一致的狀態即可。要麼是該文件完全寫入,要麼是而不是。如果文件是部分寫入的,如果容器沒有實際「看到」它也沒關係。

現在的問題是: 我該如何保證數據的一致性?具體來說,你如何使IO操作作爲事務處理?你會建議什麼?我應該自己實施一些事情嗎?或者是否有容器提供這種功能?

這是我到目前爲止有:

  • 創建一個新的歸檔文件,重命名提交:不可能,檔案過大。
  • 郵編/焦油/ 7Z:不合適,寫入失敗會破壞存檔
  • TrueCrypt的:不合適的,因爲它需要一個文件系統驅動程序(即用戶點具有管理員權限)。
  • 任何需要將文件系統映射到文件的東西:不適合,非常確定,如果不是管理員就無法做到這一點,但如果可能的話,那將非常棒。
  • 將文件存儲在SQLite數據庫中:這是ACID,因此確實可能是一個解決方案。但是,它需要分割文件,因爲SQLite的BLOB容量有限。不是很優雅,但我已經準備好了。另外SQLite的事務日誌在存儲大塊的時候會變得非常大。
  • 自己實施:我寧願儘量避免這種情況,但我並不害怕這樣做。我只是覺得這個話題很複雜。

如果這個問題太籠統,請把它移到SU或其他東西。

+0

是否將USB格式化爲NTFS? – Fanael

+0

@Fanael是的,否則檔案無論如何不適合。 –

+0

在這種情況下,如果你只對Vista和以上版本感興趣,也許你應該嘗試'CreateFileTransacted'及其朋友? – Fanael

回答

1

你可能想嘗試使用類似svn或git的東西來下載加密的差異;它們通常可用於在本地重建文件,如果它被損壞。或者下載差異並使用補丁來生成最新的文件版本。

如果用戶在寫入數據的過程中拔出FLASH驅動器,則會出現其他問題。許多不可靠(在閃存塊級別,而不是文件系統級別),並且可能會損壞,以至於像NTFS或EXT3這樣的日誌文件系統無法恢復。這裏有更多的細節:https://superuser.com/questions/290060/can-flash-memory-be-physically-damaged-if-power-is-interrupted-while-writing

+0

我不控制遠程服務器。然而,你的最後一段很有趣,讓我想了一會兒。也許我只是不想處理任何事情。 –

+0

你可以在本地運行git;您可以使用其版本功能來重建受損的文件。 – patwood

0

這很簡單,真的。寫入臨時文件,然後在寫入完成時設置爲主服務器,否則請刪除並重試。

+1

正如我所說那是不可能的,檔案太大了。 –

+1

不要讓它聽起來太簡單:** [重命名()沒有fsync()安全?](http://stackoverflow.com/questions/7433057/is-rename-without-fsync-safe)** – sehe

0

也許我們的SolFS(應用程序版本)將工作。 SolFS在一個容器文件中提供了一個虛擬文件系統,它支持數據寫入的日記模式,這有助於保持文件系統的完整性。