ディスクへのデータ書き込みの遅延の背後にある哲学は何ですか?


72

Linuxでは、cpまたはなどのコマンドの実行が終了しddても、データがデバイスに書き込まれたことを意味しません。たとえば、を呼び出すsyncか、ドライブの「安全な取り外し」または「取り出し」機能を呼び出す必要があります。

そのようなアプローチの背後にある哲学は何ですか?データが一度に書き込まれないのはなぜですか?I / Oエラーが原因で書き込みが失敗する危険はありませんか?


16
読み取りおよび書き込みシステムコールは一度に1バイトで動作することができますが、ディスクドライブは固定サイズブロ​​ックの読み取りまたは書き込みしかできないことに注意してください。一度のI / Oでのバイトのオーバーヘッドは、バッファリングなしでは耐えられません。バッファリングにより、耐えられます。
ジョナサンレフラー

回答:


47

そのようなアプローチの背後にある哲学は何ですか?

効率(ディスク特性のより良い使用)とパフォーマンス(アプリケーションが書き込み後すぐに続行できるようにします)。

データが一度に書き込まれないのはなぜですか?

主な利点は、OSが連続した書き込み操作を自由に並べ替えてマージし、帯域幅の使用率を向上させることです(操作が少なくシークが少なくなります)。ハードディスクは、少数の大規模な操作が要求されたときにパフォーマンスが向上しますが、アプリケーションは代わりに多数の小規模な操作を必要とする傾向があります。別の明確な最適化は、同じブロックが短時間に複数回書き込まれた場合、OSが最後の書き込みを除くすべてを削除することも、影響を受けたファイルがその間に削除された場合、一部の書き込みをすべて削除することもできます。

これらの非同期書き込みは、システムコールが返されたに行われwriteます。これは、ユーザーにとって目に見える2番目の利点です。非同期書き込みは、データが実際にディスク上にあることを待たずに自由に作業を続行できるため、アプリケーションを高速化します。同じ種類のバッファリング/キャッシュは、最近または頻繁に読み取られたブロックがディスクから再度読み取られるのではなくメモリに保持される読み取り操作にも実装されます。

IOエラーが原因で書き込みが失敗する危険はありませんか?

必ずしも。それは、使用するファイルシステムと適切な冗長性に依存します。データを他の場所に保存できる場合、I / Oエラーは無害です。ZFSなどの最新のファイルシステムは、不良ディスクブロックを自己修復します。また、I / Oエラーが最新のOSをクラッシュさせることはありません。データアクセス中に発生した場合、影響を受けるアプリケーションに報告されます。構造的なメタデータアクセス中に発生し、ファイルシステムが危険にさらされると、読み取り専用で再マウントされるか、アクセスできなくなる可能性があります。

OSのクラッシュ、停電、またはハードウェア障害の場合には、わずかなデータ損失のリスクもあります。これが、データがディスク上に100%あることを確認する必要があるアプリケーション(データベース/金融アプリなど)の効率が低いが、より安全な同期書き込みを行う理由です。パフォーマンスへの影響を軽減するために、多くのアプリケーションは引き続き非同期書き込みを使用しますが、ユーザーがファイル(vim、ワードプロセッサなど)を明示的に保存すると最終的に同期します。

一方、ユーザーとアプリケーションの大多数は、同期書き込みが提供する安全性を必要とせず、気にしません。クラッシュまたは停電が発生した場合、多くの場合、最後の30秒間のデータを失うことが唯一のリスクです。関係する金融取引またはそれらの時間の30秒よりもはるかに大きなコストを意味する同様のものがない限り、パフォーマンスの大きな向上(幻想ではなく、非常に現実的)非同期書き込みは、リスクを大幅に上回っています。

最後に、同期書き込みは、とにかく書き込まれたデータを保護するのに十分ではありません。アプリケーションでデータが失われないことを本当に確認する必要がある場合は、火災、洪水などの災害に耐えるために、複数のディスクおよび複数の地理的場所でのデータ複製を配置する必要があります。


コストだけでなく、保存されたデータに依存する何かが行われたかどうかを検討してください。小説をタイピングして順番に保存し、電源を切ると、30秒の仕事が失われます。その30秒の値に関係なく、少なくともタイピングの過程で実際に発生した状態に回復します。 、そこから再開できます。一方、「保存」を押して、机の紙のtodoリストから何かを消すと、回復したときにハードディスクと紙の間に矛盾が生じます。これはから再開することが一般的に困難です...
スティーブ・ジェソップ

1
...だから、普通のユーザーとして、実際に失敗したことをやったと思わないように、todoリストから「小説を書き終える」前にファイルシステムを同期したいと思うかもしれません。これが、データベースなどに同期書き込みが必要な理由です。たとえデータが失われたとしても、一貫性を維持する必要があります。
スティーブジェソップ

1
@SteveJessopあなたの例には同意しますが、カジュアルなユーザーが手動で同期することは期待していません。貴重な小説を書くために使用されたエディターがドキュメントの保存時にfsyncなどを呼び出さない場合、これは修正するバグです(例:bugs.launchpad.net/ubuntu/+source/libreoffice/+bug/817326)。私はvi(vim)を使用して私のものを書きます。vimはデフォルトで保存時にfsyncを呼び出します。
jlliagre

59

書き込みが完了するまで実際に待つ必要のないプログラムに、単に速度の錯覚を与えます。ファイルシステムを同期モード(インスタント書き込みが可能)でマウントし、すべてがどれほど遅いかを確認します。

一時的にしかファイルが存在しない場合があります...プログラムは少し作業を行い、作業が完了した直後にファイルを削除します。それらの書き込みを遅らせた場合、そもそもそれらを書いたことがないことで逃げることができます。

IOエラーが原因で書き込みが失敗する危険はありませんか?

ああ、絶対に。そのような場合、通常、ファイルシステム全体が読み取り専用モードになり、すべてがひどいものになります。しかし、それはめったに起こりません。一般的なパフォーマンスの利点を失うことはありません。


特定のHDDコントローラーにはバッテリーバックアップがあるため、電源障害が発生した場合、電源が復旧するまでコミットされていないデータがコントローラーに保存されます。これにより、データを失うことがオプションではないデータベースアプリケーションで使用できます。
strattonn

Linuxは、HDDではなくRAMにまだ書き込まれていないデータを保存します。HDDにも独自のキャッシュがあります。
バラフアルビノ

プロセスが閉じたときに、プロセスによって開かれたファイルが同期されると、非常に便利です。これはプロセス自体には影響しませんが、シェルスクリプトなど(ファイルシステム全体を同期する必要があります)を単純化します
-MSalters

14
それは単なる幻想以上のものです。非同期書き込みにより、アプリケーションの全体的なパフォーマンスが向上します。
jlliagre

4
@frostschutz:一時的にしか存在しないファイルを超えて、ファイルの一部の領域が何度も書き換えられるという事実もあります。
マチューM.

26

非同期のバッファ付きI / Oは、Linuxの前やUnixの前でも使用されていました。Unixにはそれがあり、その派生物もすべてあります。

以下は、リッチーとトンプソンがCACM論文The UNIX Time-Sharing Systemで書いたものです

ユーザーには、ファイルの読み取りと書き込みの両方が同期され、バッファリングされていないように見えます。これは、読み取り呼び出しから戻った直後にデータが使用可能になり、逆に書き込み後にユーザーのワークスペースが再利用される可能性があります。実際、システムは、ファイルへのアクセスに必要なI / O操作の数を大幅に削減する、かなり複雑なバッファリングメカニズムを維持しています。


あなたの質問では、あなたも書いた:

IOエラーが原因で書き込みが失敗する危険はありませんか?

はい、書き込みは失敗する可能性があり、プログラムはそれを知らないかもしれません。決して良いことではありませんが、I / Oエラーがシステムパニックを生成する場合、この影響を最小限に抑えることができます(一部のOSではこれは構成可能です-パニックする代わりに、システムは実行を継続できますが、影響を受けるファイルシステムアンマウントまたはマウントされた読み取り専用)。その後、そのファイルシステム上のデータが疑わしいとユーザーに通知できます。また、ディスクドライブを事前に監視して、成長した欠陥リストが急速に増加しているかどうかを確認できます。これは、ドライブが故障していることを示しています。

BSDは、fsyncシステムコールを追加したため、プログラムはファイルデータがディスクに完全に書き込まれたことが確実になり、その後のUnixシステムは同期書き込みを行うオプションを提供しました。GNU ddにはconv=fsync、コマンドが終了する前にすべてのデータが書き出されていることを確認するオプションがあります。低速のリムーバブルフラッシュドライブに書き込む場合に便利です。この場合、バッファされたデータの書き込みには数分かかる場合があります。

ファイルの破損のもう1つの原因は、停電などによる突然のシステムシャットダウンです。事実上、現在のすべてのシステムは、ファイルシステムでclean / dirtyフラグをサポートしています。フラグは、書き出すデータがもうなく、ファイルシステムがアンマウントされようとしているとき、通常はシステムのシャットダウン中または手動でを呼び出して、クリーンに設定されますumount。システムは通常fsck、ファイルシステムが正常にシャットダウンされなかったことを検出すると、再起動時に実行されます。


HDDから外部ドライブに音楽をコピーするとします。外部ドライブが破損し、書き込みが失敗する可能性があります。これにより、プログラムが誤ったデータで実行されることはありません。また、外部デバイスで失敗したIOでパニックするのはやり過ぎです。
marmistrz

いい視点ね。答えを修正します。
マークプロトニック

15

多くの良い答えがありますが、もう1つ追加します... Unixはマルチプロセスおよびマルチユーザーシステムであるため、潜在的に多くのユーザーが(ほぼ)でファイル操作(特に書き込み)を行おうとしていることを忘れないでください同時。ネットワーク経由でマウントされた古い低速のハードディスクでは、これには時間がかかるだけでなく(プログラムは基本的にロックアップし、ユーザーは待機する必要があります)、多くの読み取り/書き込みヘッドの移動を引き起こしますディスクを前後に。

そのため、代わりに、書き込みを待機しているファイルはしばらくメモリに保持され、ディスク上の最終位置でソートされます...そして、バッファがいっぱいになったとき、またはディスク同期デーモンが必要な秒数(通常は約30秒だと思います)-バッファ全体がディスクに「順番に」書き出され、書き込みヘッドは1回連続してスイープするだけで、ファイルをディスクに書き込みます。それは行きました...場所を飛び回る代わりに。

ソリッドステートデバイスはもちろんのこと、今日の高速ディスクのおかげで、ゲインははるかに小さくなります。特にホームlinuxシステムでは、一度に1人のユーザーしか動作せず、少数のプログラムしかありません。

とにかく、要求された以上の(キャッシュ/バッファへの)読み込みによる読み取りの予測と、書き込みを待機しているデータをソートして「ワンモーション」で書き込むことができる組み合わせは、実際には非常に良いアイデアでした特に、多くのユーザーが大量の読み取りと書き込みを行うシステムでは時間がかかります。


2
XFSは、書き出すまでデータをどこに置くかさえも決定しません。遅延割り当ては、アロケーターにその決定の基礎となるより多くの情報を提供します。ファイルが最初に書き込まれたとき、それが4kファイルか1Gでまだ成長中のファイルかを知る方法はありません。どこかに10Gの連続した空き領域がある場合、4kファイルを先頭に配置しても意味がありません。大きなファイルを大きな空き領域の先頭に置くと、断片化が減少します。
ピーターコーデス

13

これはLinuxに固有のものではなく、ページキャッシュと呼ばれます(Linuxは非常に優れています)。http://linuxatemyram.com/も参照してください。そのため、ファイルが書き込まれ、数秒後に再度読み取られる場合、ディスクI / Oはほとんど必要ありません。

主な利点は、多くのシステムに多くのRAMがあり、その一部はカーネルがキャッシュとして使用できることです。そのため、一部のファイル操作ではこのキャッシングを活用できます。また、ディスクI / O時間はRAMよりもはるかに遅くなります(通常、SDDの場合は数千倍、メカニカルハードディスクの場合は100万倍近く遅くなります)。

アプリケーションコードは、このキャッシュについてのヒントを与えることができます参照して例えばposix_fadvise(2) のmadvise(2)


8

回転するプラッタはRAMよりも低速です。この事実を「隠す」ために、読み取り/書き込みのキャッシュを使用します。

書き込みIOの便利な点は、ディスクIOがすぐに発生することを必要としないことです。読み取りとは異なり、ディスクで読み取りが完了するまでデータをユーザーに返すことはできません。

したがって、書き込みはソフトな時間制約の下で動作します-持続スループットがディスクのスループットを超えない限り、書き込みキャッシュでパフォーマンスのペナルティの多くを隠すことができます。

また、キャッシュを書き込む必要があります-回転ディスクは比較的低速です。ただし、最新のRAIDタイプを使用すると、操作に大きなペナルティが生じます。

たとえば、RAID 6では、1つの書き込みIOを完了するために次のことが必要です。

  • 更新ブロックを読む
  • 読み取りパリティ1
  • 読み取りパリティ2
  • 新しいブロックを書く
  • 書き込みパリティ1
  • 書き込みパリティ2

したがって、各書き込みは実際には6回の IO操作です。特に、大きなSATAドライブのような遅いディスクがある場合、これは非常に高価になります。

しかし、素晴らしい簡単な解決策があります-合体を記述します。バッファに「フルストライプ」書き込みを構築できる場合、ディスクからパリティを読み取る必要はありません。メモリにあるものに基づいて計算できます。

これを行うことは非常に望ましいことです。そうすれば、あなたはもはや書き込み増幅を持たないからです。実際、RAID 1 + 0よりも書き込みペナルティが低くなります。

考慮してください:

RAID 6、8 + 2-10スピンドル。

書き込む8つの連続したデータブロック-キャッシュでパリティを計算し、各ディスクに1つのブロックを書き込みます。8回につき10回の書き込みは、1.25の書き込みペナルティを意味します。RAID 1 + 0の10個のディスクには、まだ2の書き込みペナルティがあります(各サブミラーに書き込む必要があるため)。そのため、このシナリオでは、実際にRAID 6のパフォーマンスをRAID1 + 0よりも向上させることができます。しかし、実際の使用では、混合IOプロファイルがもう少し得られます。

したがって、書き込みキャッシュは、RAIDセットの認識パフォーマンスに大きな違いをもたらします-RAM速度で書き込みを行い、書き込みペナルティが低くなります-実行すると、持続スループットが向上します。

そうしないと、SATAのパフォーマンスが非常に遅くなりますが、それに6を掛けて競合を追加します。書き込みキャッシュを使用しない10ウェイSATA RAID-6は、RAIDを使用しない単一のドライブよりも少し高速になりますが、それほどではありません。

ただし、注意してください-電力損失はデータ損失を意味します。キャッシュのフラッシュサイクル、キャッシュのバッテリーバックアップ、またはSSDまたはその他の不揮発性キャッシュを使用することで、これを軽減できます。


7

他の答えのどれも遅れた配分について言及しませんでした。XFS、ext4、BTRFS、およびZFSはすべてそれを使用します。XFSはext4が存在する前から使用していたため、例として使用します。

XFSは、書き出すまでデータをどこに置くかさえも決定しません。 遅延割り当ては、アロケーターにその決定の基礎となるより多くの情報を提供します。ファイルが最初に書き込まれたとき、それが4kファイルか1Gでまだ成長中のファイルかを知る方法はありません。どこかに10Gの連続した空き領域がある場合、4kファイルを先頭に配置しても意味がありません。大きなファイルを大きな空き領域の先頭に置くと、断片化が減少します。


4

ここにある他のすべての答えは、少なくとも通常の場合にはほとんど正しいものであり、私の前にそれらのいずれかを読むことをお勧めしますが、ddとddには書き込みキャッシュを含まない典型的なユースケースがあります。書き込みキャッシュは、主にファイルシステムレベルで実装されます。通常、rawデバイスは書き込みキャッシュを行いません(raidやlvmなどの複数のデバイスドライバーは別のボールです)。ddはrawブロックデバイスでよく使用されるため、bsおよび関連オプションを提供して、rawデバイスでのパフォーマンス向上のために大量の書き込みを許可します。両方のエンドポイントが通常のファイルである場合、これはあまり役に立ちません(ただし、この場合、大量の書き込みで使用されるシステムコールは少なくなります)。これが特に見られる他の一般的な場所は、ユーザー空間のファットファイルシステムの実装であるmtoolsパッケージです。フロッピードライブでmtoolsを使用すると、ツールが完全に同期し、フロッピードライブが非常に遅くなるため、常に非常に遅く感じます。フロッピーのマウントとカーネルファットファイルシステムの使用は、同期のumountを除き、応答性が非常に高くなります(特に、フロッピーなどのリムーバブルデバイスの場合、データの損失を防ぐために非常に重要です)。特別に構成されたデータベース(独自の書き込みキャッシュを実装する)、tar、chdsk、mkfs、mtなどの特殊デバイスおよびファイルシステムツールなどのrawデバイスで定期的に使用されていることを知っているプログラムは他にもわずかです。フロッピーのマウントとカーネルファットファイルシステムの使用は、同期のumountを除き、応答性が非常に高くなります(特に、フロッピーなどのリムーバブルデバイスの場合、データの損失を防ぐために非常に重要です)。特別に構成されたデータベース(独自の書き込みキャッシュを実装する)、tar、chdsk、mkfs、mtなどの特殊デバイスおよびファイルシステムツールなどのrawデバイスで定期的に使用されていることを知っているプログラムは他にもわずかです。フロッピーのマウントとカーネルファットファイルシステムの使用は、同期のumountを除き、応答性が非常に高くなります(特に、フロッピーなどのリムーバブルデバイスの場合、データの損失を防ぐために非常に重要です)。特別に構成されたデータベース(独自の書き込みキャッシュを実装する)、tar、chdsk、mkfs、mtなどの特殊デバイスおよびファイルシステムツールなどのrawデバイスで定期的に使用されていることを知っているプログラムは他にもわずかです。


4
Linuxブロックデバイスは、デフォルトでページキャッシュを読み書きします。O_DIRECTキャッシュをバイパスする場合に使用する必要があります。 dd oflag=direct。IIRC、ブロックデバイス上の直接I / Oにデフォルト設定される一部のユニックス。(そして、アライメントされたブロックの読み取り/書き込みが必要です。Linuxは、とにかくページキャッシュを書き込むだけなので、そうではありません。)
Peter Cordes

3

哲学はデフォルトでは安全ではありません。

可能な2つの合理的で明白な戦略があります。ディスクへの書き込みをすぐにフラッシュするか、書き込みを遅らせるかです。UNIXは歴史的に後者を選択しました。安全を確保するため、fsync後で電話する必要があります。

ただし、オプションを使用してデバイスをマウントすることで事前に安全性を指定することもsync、で開くことでファイルごとに安全性を指定することもできますO_SYNC

UNIXはコンピューターの専門家向けに設計されていることを忘れないでください。「デフォルトで安全」は考慮されていません。安全とは、I / Oが遅いことを意味し、初期のシステムでは実際にI / Oが遅いため、価格が高くなります。残念ながら、これは重大な変更ではありませんが、UNIXもLinuxもデフォルトのセーフに切り替えませんでした。


6
アプリケーションとユーザーの大部分は、同期書き込みが提供する安全性を必要としないか、気にしません。クラッシュまたは停電が発生した場合、最後の30秒間のデータが失われる可能性があります。ほとんどの人は、金銭的な取引や、30秒以上かかるような類似したものがない限り、大丈夫です。同期I / Oにデフォルト設定すると、ユーザビリティを対象とするすべてのアプリケーションがO_NOSYNCを定義することを暗示していました。
jlliagre

2

スループットの大幅な向上と引き換えに、少量の信頼性を犠牲にします。

たとえば、ビデオ圧縮プログラムがあるとします。遅延書き込み(「ライトバック」)の場合:

  1. フレームの圧縮に10msかかります
  2. ディスクへの書き込みフレームを発行する
  3. ディスクが書き込み完了を確認するまで10ms待ちます
  4. 後藤1

  1. フレームの圧縮に10msかかります
  2. ディスクへの書き込みフレームの発行(バックグラウンドで完了)
  3. 後藤1

2番目のバージョンはCPUとディスクを同時に使用できるため2倍の速度で表示されますが、最初のバージョンは常にどちらか一方を待機しています。

一般に、ストリーミング操作とバルクファイル操作のライトバック、およびデータベースとデータベースのようなアプリケーションのライトスルーが必要です。


1

多くのアプリケーションでは、ストレージデバイスは断続的にデータの読み取りでビジー状態になります。ストレージデバイスがデータの読み取りでビジーでない時間までシステムが常に書き込みを延期できる場合、アプリケーションの観点からは、書き込みの完了にゼロ時間がかかります。書き込みが瞬時ではない唯一の状況は、次の場合です。

  1. 書き込みバッファは、書き込みが実際に完了するまで、遅延書き込み要求を受け入れられなくなるまでいっぱいになります。

  2. 書き込みが保留されているデバイスをシャットダウンまたは削除する必要があります。

  3. アプリケーションは、書き込みが実際に完了したことの確認を特に要求します。

実際、書き込みが実際に行われる必要があるのは、上記の要件のためだけです。一方、デバイスがアイドル状態になっているときに保留中の書き込みを実行しない理由は一般にないため、多くのシステムが書き込みを実行します。


0

これもあります:

「Hi、Joe Moe」の 書き込みは、「Hi、」の 書き込み「Joe」の 書き込み「Moe」の書き込み
よりも高速です。


そしてまた:

「こんにちは、元気ですか?」と書いてください。
より速い:
「こんにちは、元気ですか?」 「Howdy、how are you?」

書いて削除します 「こんにちは、元気ですか?」

書いて削除します

変更や集約は、ディスクよりもRAMで行う方が適切です。ディスク書き込みのバッチ処理により、アプリケーション開発者はこのような懸念から解放されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.