php 如何删除memcached中具有相同前缀键的项目?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10792338/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 23:04:23  来源:igfitidea点击:

How to delete items with same prefix key in memcached?

phpmemcachedprefix

提问by northtree

For example, I have some cached items with same prefix, such as

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

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

Can I remove such 'app_xxxxxx' items by any memcached commands?

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

回答by ziad-saab

Memcached does not offer this functionality out of the box so you have to build it in yourself.

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

The way I solve this is by defining a prefix (or namespace) in my application for groups of keys. Any key that I set in memcached has that prefix before it. Whenever I want to "delete" stuff from Memcached, I just change the prefix. And whenever I want to lookup a key in Memcached, I add that prefix to it.

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

In your case, you could start by setting the prefix to, say, MyAppPrefix1, so your keys will be stored as MyAppPrefix1::app_333333, MyAppPrefix1::app_444444.

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

Later on when you want to "delete" these entries, set your application to use MyAppPrefix2. Then, when you try to get a key from Memcached called app_333333, it will look for MyAppPrefix2::app_333333and will not find it the first time around, as if it had been deleted.

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

回答by billynoah

How about this function in php:

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

Deletes keys beginning with $prefix and returns a list of all keys removed. I ran this on 30,000+ keys just now on a shared server and it was pretty quick - probably less than one second.

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

回答by Joyce Babu

This is a hack that works, albeit a bit slow. On a server with 0.6 million keys, it took half a second to complete.

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

回答by Last person

We can not do that in only one request to memcache. We just can do this:

我们不能只在对 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);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

And call this function like this:

并像这样调用这个函数:

        $prefixes = array();

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

        $this->clearByPrefix($prefixes);