Кэширование APC и атомарные операции - PullRequest
1 голос
/ 12 марта 2010

Я думаю об интеграции некоторой логики кэширования в моем приложении.

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

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

1 Ответ

1 голос
/ 01 октября 2010

Что ж, если вы говорите об одной операции, она будет атомарной (в зависимости от того, как работает 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, но перезаписывают друг друга). Если это большая проблема, вы должны прочитать о двойной проверке блокировки

...