100台のサーバーでコマンドを実行し、それぞれが出力をNFS共有上の同じファイルにリダイレクトする場合、結果のファイルはきちんとインターリーブされますか、それとも破損する可能性がありますか?
たとえば、このコマンドが100台のサーバーで実行された場合:
find / type -f >> /some_server/share/file_list.txt
それは壊れているでしょうか?
ps。コマンドは単なる例であり、実際にはファイルをリストしていません
要するに:はい、複数のNFSクライアントからの同時書き込みは破損します。
OSはファイルが追加モードで開かれていることを認識し、その間にファイルを拡張した可能性のある他のプロセスに関係なく、各書き込み呼び出しの前にファイルの現在の終わりをアトミックにシークするため、ローカルでの同時追加は適切にインターリーブされます。
しかし、NFSでは、そのような運はありません。 Linux NFS FAQ はそれを明白に述べています:
A9。複数のクライアントでO_APPENDを使用してファイルを開くと、ファイルが破損するのはなぜですか?
A。 NFSプロトコルはアトミックな追加書き込みをサポートしていないため、どのプラットフォームのNFSでも追加書き込みがアトミックになることはありません。
2.4.20より新しいカーネルのLinuxNFSクライアントを含むほとんどのNFSクライアントは、「オープンに近い」キャッシュの一貫性をサポートしています。A8。オープンに近いキャッシュの一貫性とは何ですか?
A。異種のNFSクライアント間の完全なキャッシュコヒーレンシを実現するには非常にコストがかかるため、NFSは、ほとんどの日常的なタイプのファイル共有の要件を満たす、より弱いものに落ち着きます。 [...]アプリケーションがファイルを閉じると、NFSクライアントは保留中の変更をファイルに書き戻し、次のオープナーが変更を表示できるようにします。これにより、NFSクライアントは、close()からの戻りコードを介してサーバー書き込みエラーをアプリケーションに報告する機会も得られます。この動作は、オープンに近いキャッシュの一貫性と呼ばれます。
NFS 書き込み操作 には、書き込む位置と書き込まれるデータが含まれているだけです。ファイルの終わりがどこにあるかを一元的に調整するための規定はありません。これは、クライアントが互いに上書きしないようにするために必要なことです。
(このページは、Linuxカーネルバージョン2.6について主に説明しており、3.xについては言及していないため、少し古いように見えます。ただし、NFSバージョン4はカーネルサポートに関連して言及されているため、答えはv4にも当てはまると考えられます。 。)
最近のLinuxとNFSv3共有で行われた小さなテスト:
2つのクライアントで同時にシェルループ(for ((i=0 ; i<9999 ; i++)) ; do printf "$id %06d\n" $i >> testfile ; done
)に数値を書き出すと、出力が適切に破損します。その一部:
barbar 001031
foo 000010
32
foo 000011
33
foo 000012
ここで、あるマシンの最初のループはbarbar
で行を書き込み、別のマシンの別のループはfoo
行を書き込みました。 barbar 001032
と表示される行は、foo 000010
行と同じ位置から開始して書き込まれ、長い行の最後の番号のみが表示されます。 (この場合、リダイレクトはループ内にあるため、ファイルは実際にはprintf
ごとに開かれ、閉じられます。ただし、ファイルが開かれたときのファイルの終わりを見つけるのに役立つだけです。)
ファイルが常に開いたままになっていると、ファイルが閉じられたときにクライアントシステムがサーバーに変更を書き込むことだけが約束されるため、より大きなブロックが上書きされる可能性があります。切り捨てによってファイルがクリアされるだけで、ファイルを閉じるときに他のクライアントによるそれ以上の書き込みが妨げられないため、開いているときにファイルを切り捨てても、それほど変更はありません。