【问题标题】:How to delete items with same prefix key in memcached?如何删除memcached中具有相同前缀键的项目?
【发布时间】:2012-06-03 06:35:32
【问题描述】:

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

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

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

【问题讨论】:

标签: php memcached prefix


【解决方案1】:

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

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

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

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

【讨论】:

  • 你如何删除旧条目?按时间到期?
  • @AlfonsoFernandez-Ocampo 是的,为什么不呢? Memcache 会在需要时删除它们
  • 看起来不错,但是,Memcached过了过期时间或者快满的时候会删除吗?
【解决方案2】:

这个函数在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 多个密钥,而且速度非常快 - 可能不到一秒。

【讨论】:

  • 这不能保证有效。 php.net/manual/en/memcached.getallkeys.php "由于 memcache 不保证返回所有键,您也不能假设所有键都已返回。"
  • 感谢@TimMartens 指出这一点。我想它和你能得到的一样好?我希望有更多关于何时以及为什么 getAllKeys() 方法可能会失败的信息......你能对此有所了解吗?这些文档非常无用。
【解决方案3】:

这是一个有效的技巧,虽然有点慢。在拥有 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));
        }
    }

【讨论】:

    【解决方案4】:

    我们不能只在一个内存缓存请求中做到这一点。我们可以这样做:

    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);
    

    【讨论】:

    • 即使你的代码看起来很容易理解,你也可以解释它的作用以及为什么你认为这个解决方案可以帮助提问者。顺便说一句,当你可以调用 strpos 时, preg_match 真的是大材小用。
    • 也许我应该在我的代码中添加更多 cmets :) 关于 preg_match,我不认为这是矫枉过正。你知道,这对这个案子来说只是一件简单的事情。我什至打算让正则表达式在未来变得更加复杂。 :) 感谢您的评论兄弟!
    猜你喜欢
    • 2017-03-22
    • 1970-01-01
    • 1970-01-01
    • 2022-12-16
    • 1970-01-01
    • 2020-04-16
    • 2022-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多