APC缓存和原子操作

时间:2010-03-12 16:23:05

标签: php apc

我正在考虑在我的应用中集成一些缓存逻辑。

主要是,它会将对象和对象列表缓存到APC。我会 为对象实现一种自动失效的方法 已更新/删除。

然而,原子性怎么样?我怎样才能确保操作是原子的?

1 个答案:

答案 0 :(得分: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