2012-05-29 1 views
23

К примеру, у меня есть некоторые кэшированные элементы с таким же префиксом, такие какКак удалить элементы с одним и тем же ключом префикса в memcached?

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

Может ли я удалить такие «app_xxxxxx» пункты любой Memcached команд?

+1

http://stackoverflow.com/questions/1595904/memcache-and-wildcards –

ответ

36

Memcached не предлагает эту функциональность из коробки, поэтому вам нужно ее самостоятельно построить.

Способ, которым я решаю это, - определить префикс (или пространство имен) в приложении для групп ключей. Любой ключ, который я установил в memcached, имеет этот префикс перед ним. Всякий раз, когда я хочу «удалить» материал из Memcached, я просто изменяю префикс. И всякий раз, когда я хочу найти ключ в Memcached, я добавляю к нему этот префикс.

В вашем случае вы можете начать с установки префикса до, скажем, MyAppPrefix1, поэтому ваши ключи будут сохранены как MyAppPrefix1::app_333333, MyAppPrefix1::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, я не думаю, что это перебор. Вы знаете, это просто для этого случая. Я даже предполагаю, что регулярное выражение будет более сложным в будущем. :) Спасибо за ваш комментарий bro! –

0

Это хак, который работает, хотя и немного медленно. На сервере с 0,6 миллионами ключей понадобилось полсекунды.

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