Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php APC缓存和原子操作_Php_Apc - Fatal编程技术网

Php APC缓存和原子操作

Php APC缓存和原子操作,php,apc,Php,Apc,我正在考虑在我的应用程序中集成一些缓存逻辑 它主要将对象和对象列表缓存到APC。我会的 实现一种方法,一旦对象 已更新/删除 但是,原子性呢?如何确保操作是原子的?好吧,如果你说的是单个操作,它将是原子的(基于APC的工作方式)。要么全部写下来,要么一个都不写 如果您谈论的是多个操作(比如更新对象引用的每个位置),那么没有内置的东西可以防止竞争条件。相反,您需要做的是实现某种锁定,以防止其他进程尝试更新该数据 可以这样做的一种方法是,在开始操作之前,通过将一个特殊的锁“cached”项写入一个已

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

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


但是,原子性呢?如何确保操作是原子的?

好吧,如果你说的是单个操作,它将是原子的(基于APC的工作方式)。要么全部写下来,要么一个都不写

如果您谈论的是多个操作(比如更新对象引用的每个位置),那么没有内置的东西可以防止竞争条件。相反,您需要做的是实现某种锁定,以防止其他进程尝试更新该数据

可以这样做的一种方法是,在开始操作之前,通过将一个特殊的锁“cached”项写入一个已知的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\u存在,两个进程都返回false,但会相互覆盖)。如果这是一个大问题,那么您应该仔细阅读

好吧,如果您谈论的是单个操作,它将是原子的(基于APC的工作方式)。要么全部写下来,要么一个都不写

如果您谈论的是多个操作(比如更新对象引用的每个位置),那么没有内置的东西可以防止竞争条件。相反,您需要做的是实现某种锁定,以防止其他进程尝试更新该数据

可以这样做的一种方法是,在开始操作之前,通过将一个特殊的锁“cached”项写入一个已知的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\u存在,两个进程都返回false,但会相互覆盖)。如果这是一个大问题,那么您应该仔细阅读

这可能在小规模下工作,但它不是线程安全的,在原子性很重要的情况下,它不是一个可以依赖的解决方案。双重检查锁定也不是解决方案。部分原因是您链接的文章中引用的许多原因,部分原因是APC()的性质。如果PHP进程在放弃锁之前失败,它也很容易出现死锁。这看起来可能在小规模下工作,但它不是线程安全的,在原子性很重要的情况下,它不是一个可以依赖的解决方案。双重检查锁定也不是解决方案。部分原因是您链接的文章中引用的许多原因,部分原因是APC()的性质。如果PHP进程在放弃锁之前失败,它也很容易出现死锁。