使用APC / Memcache / Eaccelerator按前缀删除缓存

4
假设我已经在 apc、memcached 和 eaccelerator 中保存了这些变量:
  • article_1_0
  • article_1_1
  • article_3_2
  • article_3_3
  • article_2_4
如何删除以 article_3_ 开头的所有缓存变量(它们可能达到 10000)?
是否有办法列出缓存的变量?
5个回答

11

低效的解决方案

对于APC:

$iterator = new APCIterator('user', '#^article_3_#', APC_ITER_KEY);
foreach($iterator as $entry_name) {
    apc_delete($entry_name);
}

对于eaccelerator:

foreach(eaccelerator_list_keys() as $name => $infos) {
    if (preg_match('#^article_3_#', $name)) {
        eaccelerator_rm($name);
    }
}

要使用memcached,请查看@rik的答案

正确的解决方案

批量过期多个键的通用解决方案是对它们进行命名空间处理。要使其过期,只需更改命名空间即可:

假设你有一组键“article_3_1”,“article_3_2”等等,你可以像这样存储它们:

$ns = apc_fetch('article_3_namespace');
apc_store($ns."_article_3_1", $value);
apc_store($ns."_article_3_2", $value);

像这样获取它们:

$ns = apc_fetch('article_3_namespace');
apc_fetch($ns."_article_3_1");

通过增加命名空间来使所有内容过期:

apc_inc('article_3_namespace');

3
赞同使用 APCIterator,但需要 APC 3.1.1 或更高版本。 - Mark Baker
你好,APCIterator中的第一个参数"user"是什么意思?我在手册中找不到有关它的任何信息! - Rami Dabain
1
它表示用户缓存条目;用户缓存条目是由apc_store()等设置的变量。此参数的另一个可能值是file;文件缓存条目是缓存的脚本。 - Arnaud Le Blanc
https://dev59.com/aGDVa4cB1Zd3GeqPZhLV#10114726说它不起作用。 - Mohammad Reza Esmaeilzadeh

2

尽管文档中说APCIterator在apc >= 3.1.1中可用,但我使用的几个系统声称已经安装了apc 3.1.9,但是却没有APCIterator。如果您没有APCIterator,可以尝试使用类似以下代码:

$aCacheInfo = apc_cache_info('user');

foreach($aCacheInfo['cache_list'] as $_aCacheInfo)
    if(strpos($_aCacheInfo['info'], 'key_prefix:') === 0)
        apc_delete($_aCacheInfo['info']);

在这个例子中,我们正在检查键中的前缀,但您可以使用 preg_match 等函数,并实现类似于 APCIterator 的功能。

1

有一个APCIterator可以帮助你在APC中搜索键。实例化APCIterator。

APCIterator::valid()表示仍有键需要迭代。APCIterator::key()返回apc键。APCIterator::next()将迭代器位置移动到下一个项目。

// APC
$iterator = new APCIterator('user', '/^article_3_/');

while($iterator->valid()) {
     apc_delete($iterator->key());
     // You can view the info for this APC cache value and so on by using 
     // $iterator->current() which is array
     $iterator->next();
}

对于memcache,您可以使用Memcached并使用getAllKeys方法

// Memcached 
$m = new Memcached();
$m->addServer('mem1.domain.com', 11211);

$items = $m->getAllKeys();

foreach($items as $item) {
    if(preg_match('#^article_3_#', $item)) {
        $m->delete($item);
    }
}  

2
除了代码之外,总是最好提供一些解释。 - whoan
而且作为额外的内容,回答完整的问题。你漏掉了OP询问“有没有办法列出缓存的变量?”这一部分。 - RichardBernards
我已经扩展了我的答案。感谢您的反馈 :) - Nikolai Alexiev

1

如果有可能使用memcached的替代方案,scache支持结构化键空间。通过它,您可以将数据存储到嵌套路径中:

scache_shset($conn, 'article/1/0', $data10);
scache_shset($conn, 'article/3/0', $data30);
scache_shset($conn, 'article/3/1', $data31);

最终通过删除父节点来销毁数据

scache_shunset($conn, 'article/3');

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接