Memcachedは、衝突を回避するためのシステムを提供しないため、静的データの単純なキャッシュ用に設計されています。
データ記録
標準的な状況
PHPアプリケーションが単一のサーバーで実行され、memcachedがリモートマシンで実行されるとします。 アプリケーションはWEBではないため、1つのプロセスしか存在しないため、問題なく同じセルを読み書きできます。 プロセスの直線性により、同じセルに異なるデータを同時に書き込むことはできません。
2つ以上のプロセス
今日、アプリケーションを2つのサーバーに分割する必要があり、問題が始まりました。 memcacheへの書き込み中に衝突が発生しました。 ケースの80%で、アプリケーションはデータを1つのセルに同時に書き込もうとすることが判明しました。 理想的なソリューションは共有メモリを使用することですが、Memcachedとは異なり、拡張性はありません。 大量のコードとアプリケーションの書き換えに要する推定時間のため、松葉杖を追加することが決定されました。
Aglorythmの読み取り-書き込み
2つのデーモンが記録のために単一のデータセルに同時にアクセスしていることを想像してください。これは避けられません。 通常の状況では、衝突が発生します。 次のように行動します。
- Process1はメモリからuniqidを読み取りますが、空です。
- Process1は、uniqidにそのpidとサーバー番号を書き込みます
- Process1はuniqid値をチェックします。 キーと一致する場合、データを書き込みます。
状況に応じて、キーを削除します。 あなたは、プロセスが異常終了したときにデータセルのロックを解除します記録時間を追加することができます1 - Process2はメモリ位置からuniqidを読み取りますが、空ではありません。
- Process2は待機中です。たとえば、usleep(rand(1,5)); (周期的に)隣接オブジェクトのセルにアクセスしてもデータを書き込む必要がある場合。 記録する必要はないかもしれませんが、記録を防ぐためにセルをブロックするだけです。
- Process2はメモリからuniqidを読み取りますが、空です。 さらに、最初のプロセスと同じです。
- Process3はメモリからuniqidを読み取りますが、空です。
- Process3は、pidとサーバー番号を使用してuniqidを書き込みます
- Process3はuniqid値をチェックします。 彼のキーと一致しません。
- Process3はエラーを返すか、アルゴリズムに従って動作します。
- 記録後、プロセスはuniqidからpidを削除する必要があります(これは状況によって異なります)
memcacheの同じセルを異なるPIDで上書きする2つのデーモンのテスト結果。
:
: 17699
: 100000
: 89.012994 .
:
: 92999
: 100000
: 139.522396 .
デーモンアルゴリズム:
- ミューテックスが閉じている間に、もう一度確認してください。
- ミューテックスが開いている場合は、ミューテックスを記述します。
- ミューテックスが正しい場合-書き込み、正しくない場合-最初に進みます。
- データの書き込み
- ミューテックスを削除する
テストでは、データのほぼ半分が失われたことが示されています。
通常の開発者(Redis、MemcacheDBなど)の場合、この奇跡を書き直す必要があります。
このアルゴリズムを使用すると、MemcacheをGearmanとして使用することもできます。 キャッシングサーバー自体の欠点は残っていますが、ほとんどの場合は現れません。