2012-05-29 59 views

回答

36

Memcached不提供这种功能,所以你必须自己构建它。

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

对于您的情况,您可以将前缀设置为例如MyAppPrefix1,这样您的密钥将被存储为MyAppPrefix1::app_333333MyAppPrefix1::app_444444

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

+1

如何删除旧条目?到期时间? –

+0

@ AlfonsoFernandez-Ocampo是的,为什么不呢? Memcache会在需要 – yefrem

+0

时删除它们,看起来不错,但是,Memcached会在到期时间后或它将要满时删除? – kscius

4

这个怎么样函数在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; 
} 

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

+2

这不能保证能正常工作。 http://php.net/manual/en/memcached.getallkeys.php “由于memcache不能保证返回所有密钥,所以您也不能认为所有密钥都已返回。” –

+2

感谢您指出这一点@TimMartens。我想这跟你能得到的一样好?我希望有更多关于getAllKeys()方法何时以及为什么会出现的更多信息。你能对此有所了解吗?文档是相当无益的。 – billynoah

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

即使你的代码看起来很容易理解,你也可以解释它的作用,以及为什么你认为这个解决方案可以帮助提问者。顺便说一句,preg_match当你可以调用strpos时,确实是一个矫枉过正的问题。 –

+0

也许我应该在我的代码中添加更多评论:) 关于preg_match,我不认为这太过矫枉过正。你知道,对于这种情况只是一件简单的事情。我甚至打算将来的正则表达式会更复杂。 :)感谢您的评论兄弟! –

0

这是一个工作,虽然有点慢黑客攻击。在拥有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)); 
     } 
    } 
相关问题