私は自分のアプリにいくつかのキャッシュロジックを統合することを考えています。
主に、オブジェクトとオブジェクトリストをAPCにキャッシュします。オブジェクトが更新/削除されたら、それらを自動的に無効にする方法を実装します。
しかし、原子性はどうですか?操作がアトミックであることを確認するにはどうすればよいですか?
単一の操作について話している場合は、(APC の動作に基づいて) アトミックになります。全部書くか、何も書かないか…
複数の操作について話している場合 (オブジェクトが参照されるすべての場所を更新する場合のように)、競合状態を防ぐために組み込まれているものは何もありません。代わりに、何らかのロックを実装して、他のプロセスがそのデータを更新しようとするのを防ぐ必要があります。
これを行う 1 つの方法は、操作を開始する前に、特別なロック "キャッシュ" アイテムを既知の ID に書き込むことによって、キャッシュされた各アイテムを "ロック" することです (データベースでの行レベルのロックを考えてください)。
したがって、影響を受けるキャッシュ ID の配列を想定すると、次のようになります。
function getLocks($cacheIds) {
$locked = array();
foreach ($cacheIds as $cacheId) {
if (apc_exists($cacheId . '_locked')) {
//Another process has this id locked, clear all locks and return
foreach ($locked as $id) apc_delete($id . '_locked');
return false;
} else {
//Use a short TTL to prevent issues if this process dies
apc_store($cacheId . '_locked', 60);
$locked[] = $cacheId;
}
}
return true;
}
function releaseLocks($cacheIds) {
foreach ($cacheIds as $cacheId) {
apc_delete($cacheId . '_locked');
}
}
したがって、次のように簡単に呼び出すことができます。
if (getLocks($cacheIds)) {
//Do your operation here
releaseLocks($cacheIds);
}
ここで、これは 2 つのプロセスが同時に同じキーをチェックするわずかな可能性を妨げないことに注意してください (したがって、両方とも に対して false を返しますがapc_exists
、互いに上書きします)。これが大きな問題である場合は、二重チェックのロックについて読む必要があります