2010-03-12 3 views
0

Я собираюсь интегрировать некоторую логику кэширования в свое приложение.Кэширование APC и атомные операции

В основном, он будет кэшировать списки объектов и объектов в APC. Я буду реализовать способ для их автоматического аннулирования, как только объект будет обновлен/удален.

Однако, что относительно атомарности? Как я могу убедиться, что операции являются атомарными?

ответ

1

Ну, если вы говорите об одной операции, она будет атомарной (основанной на том, как работает APC). Либо все это будет написано, либо ничего не будет ...

Если вы говорите о нескольких операциях (как и при обновлении каждого места, на которое ссылается объект), то для предотвращения состояния гонки ничего не создано. Вместо этого вам нужно будет выполнить некоторую блокировку, чтобы другие процессы не пытались обновить эти данные.

Один из способов сделать это - «заблокировать» каждый кешированный элемент, записав особый замок «кешированный» элемент на известный идентификатор перед запуском операции (подумайте о блокировке уровня строк в базах данных).

Таким образом, предполагая, что массив пострадавших кэша идентификаторами:

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); 
} 

Теперь, нужно учитывать, что это не мешает крошечную вероятность двух одновременно проверяются процессы для одного и того же ключа (и, следовательно, оба возвращают false для apc_exists, но переписывают друг друга). Если это большая проблема, то вам следует прочитать на double-checked locking

+2

Возможно, это работает в небольших масштабах, но не является потокобезопасным и не является решением, на которое можно положиться в случае, когда атомарность важна. Двойная проверка блокировки также не является решением. Частично по многим причинам, указанным в самой статье, которую вы связали, и частично из-за характера APC (http://stackoverflow.com/questions/4468805/apc-values-randomly-disappear). Он также подвержен взаимоблокировкам, если PHP-процесс завершился неудачей, прежде чем отказаться от блокировки. – DougW

Смежные вопросы