Dropbox: ストリーミングによるファイルの同期

https://tech.dropbox.com/2014/07/streaming-file-synchronization/

1 comment | 0 points | by WazanovaNews 約3時間前 edited


Jshiike 約5時間前 edited | ▲upvoteする | link

BoxがGEに採用されたり、IPOのタイミングが話題になったり。また、AmazonがZocaloで参入してきたりと、ファイルシェアの分野もにぎやかになってきました。

それに対してDropboxは、ファイル共有時間を短縮するストリーミング方式の採用を発表しています。

1) ファイルシステム

  • Dropboxは、従来のファイルシステムのディレクトリツリーにおけるルートディレクトリにあたるところを、ネームスペースで抽象化している。各ユーザがルートのネームスペースを持ち、共有フォルダは一つもしくは複数のルートネームスペースにマウントしたネームスペースになっている。つまり、ユーザがネームスペースをもつかたちで、その逆の関係ではない。この抽象化により、Dropboxサーバの全てのファイルとディレクトリは、ネームスペースと相対パスという二つのバリューでユニークに定義できる。
  • 各ファイルは4MBごとのブロックに分割され、SHA-256でハッシュされ保存される。ファイルのコンテンツは、ブロックリストと呼んでいるこのSHA-256ハッシュのリストでユニークに判別される。
  • Server File Journal (SFJ) は、巨大なメタデータDBで、ファイルのコンテンツは持たず、ブロックリストだけを保持している。append-onlyのレコードで、ファイルの各行がファイルのユニークなバージョンとなっている。スキーマのキー列は、ネームスペースID (NSID), ブロックリスト、ジャーナルID (JID: ネームスペース内で単調増加する), Dropboxサーバタイプ。
  • サーバタイプとしては、ハッシュと暗号化されたコンテンツのkey/valueストアであるブロックデータサーバ(ユーザ、ファイル、ブロックの関係については関知しない。)と、ユーザ/ネームスペース/SFJを管理するメタデータサーバがある。
  • サーバ間のコミュニケーションは必要がある場合は内部のRPCが利用される。

2) 従来のファイル共有の仕組み

  • 各デスクトップクライアントはSFJにおける位置を示すカーソル(JID)をもち、サーバとどのように更新されているかをコミュニケートできる。
  • ファイルがアップロードされる際、クライアントはネームスペースとパスを使ってブロックリストをコミットしようとする。メタサーバは、ハッシュが既知のものか?ユーザ/ネームスペースはアクセスできるものがるか?をチェックして、足りないブロックをコミットするように返す。新規ファイルの場合は、全てのブロックをコミットするように指示することになる。
  • 次にクライアントはブロックサーバと通信し、ブロックを追加する。リクエスト単位での最大バイトの制限があるので、複数のリクエストになる。
  • そして、クライアントは再度メタサーバに通信し、今度はSFJに新しい行が追加され、OKが返ってくる。
  • ファイルのダウンロードの際、まずアイドル状態のクライアントはメタサーバとロングポール接続を保持している。更新情報があることを把握すると、クライアントがメタデータサーバに新しいSFJの行を連絡するようにリクエストし、これがカーソルベースなので、新しいエントリーだけが返ってくる。
  • そしてブロックサーバからブロックがダウンロードされて、ファイルが再構築される。
  • 一連の流れを図式化したもの
  • ファイルシステムの更新状況確認、ハッシュ、コミット、ブロック保存のバッチ、リストの要求、ブロック取り出しのバッチ、再構築については、別々のスレッドで行うことで大量のファイルについて並列処理できるようになっている。

3) ストリーミングによる新しいファイル共有の仕組み

  • 一般的に大きなファイルの場合、ファイル同期の時間は、保存/取り出しのコールのためのネットワーク時間で占められる。保存バッチのコールはSFJコミットの前でなくてはいけない。更新リストのコールはSFJコミットの後でないと意味がない。しかし、取り出しのバッチはコミットに依存する必要はない。とすると、アップロードとダウンロードのクライアントの仕事をオーバーラップさせて、理想的には、ダウンロードの処理は常にアップロードの処理に一つ遅れたブロックサーバネットワークコールをすればよいのではないかと考えた。
  • 新しい流れを図式化したもの
  • ダウンロードクライアントは、まだコミットされてないファイルの一部のブロックをprefetchすることで、SFJコミットがされた時点では既にダウンロードの作業は(ほぼ)完了していることになる。
  • アップロードクライアントは振る舞いを変更する必要はないが、ダウンロードクライアントは、SFJ関連でない変更を検知する必要がある。そのために、変更リストにストリーミング同期でprefetchできるブロックリストの情報を追加した。
  • メタサーバのステート管理を、アップロードクライアントがコミットを試みて失敗する最初の時点から追うことで、ダウンロードクライアントがSFJコミット前にアクションをおこせるようにした。追加のステートはずっと保持する必要はないので、memcacheで対応。
  • クライアント側ではprefetchキャッシュにブロックを保持。
  • 正常ケースだけなく、ユーザが気が変わって、アップロードが途中で中断される場合もある。保存プロトコルに特別なリターンコードを追加して、ブロックにアクセスする際にmemcacheをチェクして、ブロックがストリーミングに対応できるかどうか、フォールバックさせるか判断できるようにした。
  • ストリーミングの効果は、大きなファイルの方が顕著で、テストでは約25%改善した。(比較グラフ

#dropbox

Back