2010-03-12 85 views
0

我正在考慮將一些緩存邏輯集成到我的應用程序中。APC緩存和原子操作

它主要將對象和對象列表緩存到APC。我將 實施一種方法,一旦對象 被更新/刪除,它們將自動失效。

然而,原子性呢?我怎樣才能確保操作是原子的?

回答

1

好吧,如果你在談論一個單一的操作,這將是原子(基於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

+2

這可能出現在小規模的工作讀,但它不是線程安全的,而不是在一個情況下,依靠其中的原子是重要的解決方案。雙重檢查鎖定也不是解決方案。部分原因是您鏈接的文章中引用的許多原因,部分原因是由於APC的性質(http://stackoverflow.com/questions/4468805/apc-values-randomly-disappear)。如果PHP進程在放棄鎖定之前失敗,它也容易出現死鎖。 – DougW 2013-04-09 21:11:40