简体   繁体   English

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

[英]How to delete items with same prefix key in memcached?

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'项吗?

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. 我在memcached中设置的任何键都有前缀。 Whenever I want to "delete" stuff from Memcached, I just change the prefix. 每当我想从Memcached“删除”东西时,我只需更改前缀。 And whenever I want to lookup a key in Memcached, I add that prefix to it. 每当我想在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_333333MyAppPrefix1::app_444444

Later on when you want to "delete" these entries, set your application to use MyAppPrefix2 . 稍后当您要“删除”这些条目时,请将您的应用程序设置为使用MyAppPrefix2 Then, when you try to get a key from Memcached called app_333333 , it will look for MyAppPrefix2::app_333333 and will not find it the first time around, as if it had been deleted. 然后,当您尝试从Memcached获取一个名为app_333333的密钥时,它将查找MyAppPrefix2::app_333333并且第一次找不到它,就像它已被删除一样。

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. 删除以$ prefix开头的键,并返回已删除的所有键的列表。 I ran this on 30,000+ keys just now on a shared server and it was pretty quick - probably less than one second. 我刚刚在共享服务器上运行了30,000多个密钥,而且速度非常快 - 可能不到一秒钟。

We can not do that in only one request to memcache. 我们不能只在memcache的一个请求中这样做。 We just can do this: 我们可以做到这一点:

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

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. 在拥有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));
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM