0
我正在考慮將一些緩存邏輯集成到我的應用程序中。APC緩存和原子操作
它主要將對象和對象列表緩存到APC。我將 實施一種方法,一旦對象 被更新/刪除,它們將自動失效。
然而,原子性呢?我怎樣才能確保操作是原子的?
我正在考慮將一些緩存邏輯集成到我的應用程序中。APC緩存和原子操作
它主要將對象和對象列表緩存到APC。我將 實施一種方法,一旦對象 被更新/刪除,它們將自動失效。
然而,原子性呢?我怎樣才能確保操作是原子的?
好吧,如果你在談論一個單一的操作,這將是原子(基於APC是如何工作的)。要麼它將全部被寫入,要麼它們都不會...
如果你在談論多個操作(如更新每個地方的對象被引用),那麼就沒有內置任何東西來防止競爭條件。相反,你需要做的是實現某種鎖定,以防止其他進程嘗試更新該數據。你可以這樣做
一種方法是由開始操作(想想數據庫行級鎖)之前寫了特殊的鎖釦「緩存」項目,以一個已知的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);
}
現在,提防這並不妨礙兩個微小的概率在同一時間處理同一個密鑰的檢查(因此,對於apc_exists
返回false,但是相互覆蓋)。如果這是一個很大的問題,那麼你應該在double-checked locking
這可能出現在小規模的工作讀,但它不是線程安全的,而不是在一個情況下,依靠其中的原子是重要的解決方案。雙重檢查鎖定也不是解決方案。部分原因是您鏈接的文章中引用的許多原因,部分原因是由於APC的性質(http://stackoverflow.com/questions/4468805/apc-values-randomly-disappear)。如果PHP進程在放棄鎖定之前失敗,它也容易出現死鎖。 – DougW 2013-04-09 21:11:40