どのような具体的な行動が必要なのだろうか。ただし、セッションを使用することは、他の種類の共有リソースを使用することと同じであるため、すべての原則、特に同時書き込みに対する保護を適用する必要があることを思い出してください。
PHP は、Memcache ストレージだけでなく、ファイル ストレージの標準実装においても非常にうまく機能します。ユーザーが実装したセッションの読み取りと保存に関しては、通常、同時アクセスに対するロックは見過ごされ、忘れられています。一方、セッションをロックすると、複数の並列リクエストの実行がシリアル化されます。これは、セッション ID ごとに複数の同時 Ajax リクエストが発生する可能性がある Web 2.0 アプリケーションにとって最適なことではありません。
これを言って申し訳ありませんが、Laravelはこの点でかなり悪い仕事をしています。ファイルドライバーでさえ、データを保存するときに試みても、まったくロックしません。彼らが実装していないのは、データを読み取る前にロックを確立する必要があるということです。そうしないと、同じデータが 2 回読み取られ、別の方法で 2 回変更され、2 回書き戻されますが、最初の変更は失われます。
この並行性の問題は、Ajax を使用せずに従来の Web ページ アプリケーションを使用する場合、または Ajax を読み取りのみに使用する場合にはおそらく発生しないため、デバッグが非常に困難です。
そのため、現在の Laravel セッション ドライバーを使用しないことをお勧めします。彼らはセッションファイルへの書き込みがかなり悪い仕事をしています (私の最初の質問は: そもそもファイルへの書き込みを再実装する必要があるのはなぜですか? PHP には既に動作するコードがあります。 C、PHP ではありません)、書き込み対象の他のすべてのものについても同じことが当てはまります。
アップデート:
最初に間違ったソースコードを見ました。コメントで述べたように、Laravel 3 はネイティブの PHP セッション ストレージ ハンドラーを使用せず、独自のハンドラーを実装しているため、ファイルに関しても、この点で完全に壊れています。
Laravel 4 は、ベータ 4 までこのレイアウトを使用していましたが、同様に壊れていました。Symfony/HTTP-Foundation の代わりに Symfony/HTTP-Foundation を使用する大幅なリワークが行われたのは最近のことです。したがって、Laravel 4 は現在、障害の責任を負いません。Symfony は責任を負います。
Symfony は、ネイティブの PHP 機能を使用してセッションをファイルに保存するセッション ストレージ ドライバーが実際にあるため、わずかに優れた仕事をします。おかえりセッションロック!\Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler は への呼び出しを行いini_set()
ます。session.save_handler
files
他のすべてのストレージ ハンドラー (明らかな理由から NullSessionHandler を除く) は、ロックなしで独自にデータの読み込みと保存を実装します。
簡単に修正できる例を見てみましょうMemcachedSessionHandler
。これを見ると、 メソッドopen()
とclose()
メソッドのコードはほとんどありませんが、ここでロックを行う必要があります。アクティブなコードはread()
and write()
(and destroy()
) のみで、Memcached クライアント オブジェクトと直接やり取りしています。したがって、ロックが行われている場所に気付いていないと仮定するのは救いです-何もありません!
Memcached は、実際には PHP 用のネイティブ セッション保存ハンドラーを提供します。http://php.net/manual/en/memcached.sessions.phpを参照してください。
簡単な修正は、NativeFileSessionHandler をほとんどコピーし、使用する Memcache クラスターにsession.save_handler = memcached
とを設定するだけです。session.save_path
保存ハンドラは適切なロックを実装します。
まさにこれを報告している未解決の問題があります: https://github.com/symfony/symfony/issues/4976現在 10 か月間公開されており、ほとんどの開発者は並行リクエストによる非常に高速なセッション読み取り操作を楽しんでいることがわかります。適切なロックを実装します。
したがって、Laravel 4 はバグのあるコードの独自の実装を取り除くためにどういうわけか正しいことを行いました (その時点でこのバグを見たという感じはありません) が、現在は Symfony コードのバグを継承しています。
あなたがすべきこと:
Zend Server は、Zend セッション クラスターを提供します。私が使用している環境では動作します。これは PHP に対して透過的であり、ロック機能を備えています。データをハードディスクに書き込み、高可用性を提供します。これはかなりまともな機能セットだと思います。考えてみてください。
Memcached のネイティブ セッション保存ハンドラーにもロック機能があります。どういうわけか高可用性のサポートが不足していると思います。もちろん、ダウンしたノードに保存されているデータはすべて失われます。結局のところ、これは非常に高速なキャッシュであり、信頼できるストレージではありません。
他のストレージについては、ロックをアトミックに取得する方法を理解する必要があります。または、同時書き込みを処理します。
たとえば、MySQL はSELECT * FROM sesstable WHERE id = sessID FOR UPDATE
. Redis は、SET によるロック メカニズムも提供します。
ロックが目的でない場合、他のオプションは、同時書き込みが発生した場合にクリーンアップを試みることです。CouchDB では競合する書き込みが可能です。それらを解決するのはクライアント アプリケーション次第です。データベースはすべての異なるバージョンへのアクセスを許可します。また、Memcached はMemcached::cas
(比較とスワップ) を提供します。これは、既に格納されている値が変更されていない場合にのみ書き込みます。失敗した場合は保存された値を読み戻し、現在のデータセットとのマージを試みてから、再試行します。