29

例如,我有一些具有相同前缀的缓存项,例如

'app_111111', 'app_222222', 'app_333333', ...

我可以通过任何 memcached 命令删除此类“app_xxxxxx”项目吗?

4

4 回答 4

40

Memcached 不提供开箱即用的此功能,因此您必须自己构建它。

我解决这个问题的方法是在我的应用程序中为键组定义一个前缀(或命名空间)。我在 memcached 中设置的任何键前面都有该前缀。每当我想从 Memcached 中“删除”内容时,我只需更改前缀即可。每当我想在 Memcached 中查找一个键时,我都会在其中添加该前缀。

在您的情况下,您可以首先将前缀设置为 , MyAppPrefix1,这样您的密钥将存储为MyAppPrefix1::app_333333, MyAppPrefix1::app_444444

稍后当您想要“删除”这些条目时,请将您的应用程序设置为使用MyAppPrefix2. 然后,当您尝试从 Memcached 中获取一个名为 的密钥时app_333333,它会MyAppPrefix2::app_333333在第一次查找但不会找到它,就好像它已被删除一样。

于 2012-05-29T02:13:16.257 回答
7

这个函数在php中怎么样:

function deletekeysbyindex($prefix) {
    $m = new Memcached();
    $m->addServer('localhost', 11211);
    $keys = $m->getAllKeys();
    foreach ($keys as $index => $key) {
        if (strpos($key,$prefix) !== 0) {
            unset($keys[$index]);
        } else {
            $m->delete($key);
        }
    }
    return $keys;
}

删除以 $prefix 开头的键并返回所有已删除键的列表。我刚才在共享服务器上运行了 30,000 多个密钥,而且速度非常快 - 可能不到一秒。

于 2014-08-06T18:50:14.583 回答
1

这是一个有效的技巧,虽然有点慢。在拥有 60 万个密钥的服务器上,完成需要半秒。

    $prefix = 'MyApp::Test';
    $len = strlen($prefix);

    $proc = popen('/usr/local/bin/memdump --servers=localhost', 'r');
    while (($key = fgets($proc)) !== false) {
        if (substr_compare($key, $prefix, 0, $len) === 0) {
            $memcached->delete(substr($key, 0, -1));
        }
    }
于 2016-05-13T16:43:23.193 回答
0

我们不能只在一个对 memcache 的请求中做到这一点。我们只能这样做:

public function clearByPrefix($prefixes = array()) {
    $prefixes = array_unique($prefixes);

    $slabs = $this->memcache->getExtendedStats('slabs');
    foreach ($slabs as $serverSlabs) {
        if ($serverSlabs) {
            foreach ($serverSlabs as $slabId => $slabMeta) {
                if (is_int($slabId)) {
                    try {
                        $cacheDump = $this->memcache->getExtendedStats('cachedump', (int) $slabId, 1000);
                    } catch (Exception $e) {
                        continue;
                    }

                    if (is_array($cacheDump)) {
                        foreach ($cacheDump as $dump) {
                            if (is_array($dump)) {
                                foreach ($dump as $key => $value) {

                                    $clearFlag = false;
                                    // Check key has prefix or not
                                    foreach ($prefixes as $prefix) {
                                        $clearFlag = $clearFlag || preg_match('/^' . preg_quote($prefix, '/') . '/', $key);
                                    }
                                    // Clear cache
                                    if ($clearFlag) {
                                        $this->clear($key);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

并像这样调用这个函数:

        $prefixes = array();

        array_push($prefixes, 'prefix1_');
        array_push($prefixes, 'prefix2_');
        array_push($prefixes, 'prefix3_');

        $this->clearByPrefix($prefixes);
于 2015-12-07T02:39:19.690 回答