web-dev-qa-db-ja.com

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

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

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

72
marmistrz

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

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

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

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

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

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

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

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

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

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

47
jlliagre

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

時々ファイルは一時的にしか存在しません...プログラムは少し仕事をして、仕事が終わった直後にファイルを削除します。これらの書き込みを遅らせた場合、そもそも書き込みを行わなかったことで問題が解決する可能性があります。

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

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

59
frostschutz

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

RitchieとThompsonがCACM論文 NIXタイムシェアリングシステム で書いた内容は次のとおりです。

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


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

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

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

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

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

26
Mark Plotnick

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

そのため、代わりに、書き込みを待機しているファイルがしばらくメモリに保持され、-sortedの後にディスクで終了する必要があります...そしてバッファがいっぱいになったとき-またはディスク-syncデーモンは必要な秒数待機していました(通常は約30秒だったと思います)-バッファー全体が「順番に」ディスクに書き出され、書き込みヘッドは1回の連続的なスイープ動作を実行するだけで済みました。ファイルをそのままディスクに書き込んでいます...あちこちジャンプするのではなく。

ソリッドステートデバイスは言うまでもなく、今日の高速ディスクとの因果関係はありますが、特に、一度に1人のユーザーだけが作業し、いくつかのプログラムだけを使用するホームLinuxシステムでは、ゲインははるかに低くなります。

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

15
Baard Kopperud

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

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

アプリケーションコードは、このキャッシングに関するヒントを与えることができます。 posix_fadvise(2)madvise(2)

13

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

書き込みについての便利なことは、IOは、ディスクIOをすぐに実行する必要がないことです。読み取りとは異なり、データをユーザーがディスクで読み取りが完了するまで。

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

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

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

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

したがって、各書き込みは実際には6 IO operations-そして特に大きな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またはその他の不揮発性キャッシュを使用することで軽減できます。

8
Sobrique

言及されている他の回答はどれも 遅延割り当て ではありません。 XFS、ext4、BTRFS、およびZFSはすべてそれを使用します。 XFSはext4が存在する前から使用していたため、例として使用します。

[〜#〜] xfs [〜#〜] は、書き出すまでデータの配置場所を決定しません。 Delayed-allocation は、決定の基準となるより多くの情報をアロケータに提供します。ファイルが最初に書き込まれるとき、それが4kファイルなのか1G-and-still-rowingファイルなのかを知る方法はありません。 10Gの連続した空き領域がどこかにある場合、4Kファイルを先頭に置いても意味がありません。大きな空き領域の最初に大きなファイルを置くと、断片化が減少します。

7
Peter Cordes

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

4
hildred

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

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

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

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

3
MSalters

スループットを大幅に向上させるために、少量の信頼性を犠牲にします。

たとえば、ビデオ圧縮プログラムを想定します。遅延書き込み(「書き戻し」)の場合:

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

Versus

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

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

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

2
pjc50

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

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

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

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

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

1
supercat

これもあります:

「こんにちは、ジョーモー」と書く
は以下より高速です:
「こんにちは」と書く
「ジョー」と書く
「萌え」と書く

そしてまた:

「こんにちは、お元気ですか」と書き込みます。
は以下より高速です:
「こんにちは、元気?」と書いてください
削除します
「お元気ですか、元気ですか」と書きます。
削除します
「こんにちは、お元気ですか」と書き込みます。

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

0
Rolf