9

私の最新の webapp の一部は、ログの一部としてかなりの量をファイルに書き込む必要があります。私が気づいた 1 つの問題は、少数の同時ユーザーがいる場合、(ファイルに追加する代わりに) 書き込み互いに上書きされる可能性があることです。これは、宛先ファイルを同時に複数の場所で開くことができるためだと思います。

flock(...)通常は優れていますが、NFSでは動作しないようです...運用サーバーがNFSアレイを使用しているため、これは私にとって大きな問題です。

私が見た中で実際の解決策に最も近いのは、ロックディレクトリを作成しようとし、それが作成されるまで待つことです。これがエレガンスに欠けていると言うのは、今年、おそらく10年の控えめな表現です.

より良いアイデアはありますか?

編集:サーバーにルートがなく、別の方法でストレージを実行することは、少なくとも私の期限内ではすぐには現実的ではないことを追加する必要があります.

4

6 に答える 6

15

ディレクトリ操作は、NFSv2 および NFSv3 ではアトミックではありません(Brent Callaghan による書籍「NFS Illustrated」、ISBN 0-201-32570-5 を参照してください。Brent は Sun の NFS ベテランです)。

NFSv2 には 2 つのアトミック操作があります。

  • シンボリックリンク
  • 名前を変更

NFSv3 では、create 呼び出しもアトミックです。

これを知っていれば、ファイルとディレクトリのスピンロックを実装できます (PHP ではなくシェルで):

現在のディレクトリをロック:

while ! ln -s . lock; do :; done

ファイルをロックする:

while ! ln -s ${f} ${f}.lock; do :; done 

ロックを解除します(実行中のプロセスが実際にロックを取得したと仮定):

現在のディレクトリのロックを解除:

mv lock deleteme && rm deleteme

ファイルのロックを解除します:

mv ${f}.lock ${f}.deleteme && rm ${f}.deleteme

削除もアトミックではないため、最初に名前の変更 (アトミック) を行い、次に削除を行います。

シンボリックリンクと名前変更の呼び出しでは、両方のファイル名が同じファイルシステムに存在する必要があります。私の提案: シンプルなファイル名のみを使用し、ファイルとロックを同じディレクトリに配置します。

于 2008-11-09T10:27:55.883 に答える
4

別の汚いハックはflock()「ローカル」ファイルに対するものであり、ローカルファイルのロックを保持している場合にのみ、NFS ファイルを開いたり書き込んだりします。

編集:flock()ページから:

flock() は、NFS や他の多くのネットワーク ファイル システムでは機能しません。詳細については、オペレーティング システムのドキュメントを確認してください。

編集2:

もちろん、アクセスを同期するために常にデータベースを使用しています(アプリがデータベースを使用していると仮定しています)。ただし、大量のロギングを行っている場合、これはかなりのパフォーマンス ヒットになります。

ログを記録するだけの場合、集中型のログ ファイルが実際に必要ですか? ローカルでログを記録できますか (必要に応じて、1 日の終わりにローテーションするときにログを結合することもできますか)。

于 2008-10-20T13:39:11.773 に答える
3

1 つの方法として、各仮想サーバー間で共有されるMemcacheインスタンスをセットアップすることが考えられます。flock()ローカルファイル操作を開始するときにファイル名のエントリをキャッシュに入れ、終了したらそれを消去することで、サルになることができます。

各サーバーは、ファイル操作の前にこのプールにアクセスでき、この「ロック」が存在するかどうかを確認できます。

// Check for lock, using $filename as key
$lock = $memcache->get($filename);

if(!$lock) {
    // Set lock in memcache for $filename
    $memcache->set($filename, 1);

    // Do file operations...

    // Blow away "lock"
    $memcache->delete($filename);
}

最も洗練されたソリューションではありませんが、セットアップ内のすべてのサーバーからのロックを比較的簡単に制御できるはずです。

于 2008-10-20T14:00:44.273 に答える
2

dio_fcntl() を使用して、NFS ボリューム上のファイルをロックすることもできます。これには dio パッケージが必要ですが、デフォルトでは php インストールに含まれていない可能性があります。

于 2010-05-21T01:55:12.230 に答える
1

NFSでflock()ファイルを使用することはできず、I / Oは非同期である可能性がありますが、NFSでのディレクトリ操作アトミックです。つまり、いつでもディレクトリが存在するか、存在しないかを意味します。

独自のNFSロック機能を実装するには、ディレクトリをロックするときにチェックまたは作成し、完了したら削除します。

残念ながら、自分で作成していない他のアプリケーションとは互換性がない可能性があります。

于 2008-10-20T18:18:16.250 に答える
0

memcache addを使用して、競合状態を回避する必要があります。

if ($memcache->add($filename, 1, 1))
{
   $memcache->delete($filename);
}
于 2008-10-20T15:17:37.067 に答える