2012-05-29 12 views

Respuesta

36

Memcached no ofrece esta funcionalidad lista para usar, por lo que debe compilarla usted mismo.

La manera en que resuelvo esto es definiendo un prefijo (o espacio de nombres) en mi aplicación para grupos de claves. Cualquier clave que configuro en memcached tiene ese prefijo antes. Cada vez que quiero "borrar" cosas de Memcached, solo cambio el prefijo. Y cada vez que quiero buscar una clave en Memcached, le agrego ese prefijo.

En su caso, puede comenzar estableciendo el prefijo, por ejemplo, MyAppPrefix1, por lo que sus claves se almacenarán como MyAppPrefix1::app_333333, MyAppPrefix1::app_444444.

Más tarde cuando desee "eliminar" estas entradas, configure su aplicación para usar MyAppPrefix2. Luego, cuando intente obtener una clave de Memcached llamada app_333333, buscará MyAppPrefix2::app_333333 y no la encontrará la primera vez, como si hubiera sido eliminada.

+1

Y ¿Cómo eliminar entradas antiguas? por tiempo de vencimiento? –

+0

@ AlfonsoFernandez-Ocampo sí, ¿por qué no? Memcache los eliminará cuando sea necesario – yefrem

+0

que se ve excelente, pero ¿Memcached lo eliminará después del tiempo de caducidad o cuando esté a punto de llenarse? – kscius

4

¿Qué hay de esta función en 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; 
} 

Elimina claves que comienzan con el prefijo $ y devuelve una lista de todas las claves eliminadas. Ejecuté esto con más de 30,000 teclas en un servidor compartido y fue bastante rápido, probablemente menos de un segundo.

+2

Esto no está garantizado para funcionar. http://php.net/manual/en/memcached.getallkeys.php "Como Memcache no garantiza devolver todas las claves, tampoco puede suponer que se han devuelto todas las claves." –

+2

Gracias por señalarlo @TimMartens. ¿Supongo que es tan bueno como puedes conseguir? Desearía que hubiera un poco más de información sobre cuándo y por qué es probable que el método 'getAllKeys()' se quede corto ... ¿puedes arrojar algo de luz sobre esto? Los documentos son bastante inútiles. – billynoah

0

No podemos hacer eso en una sola solicitud a Memcache. Sólo puede hacer esto:

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

y llamar a esta función como esta:

 $prefixes = array(); 

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

     $this->clearByPrefix($prefixes); 
+0

Incluso si su código parece fácil de entender, podría explicar lo que hace y por qué cree que esta solución ayuda al solicitante. Por cierto, preg_match cuando podrías simplemente llamar a strpos, es realmente una exageración. –

+0

Tal vez debería agregar más comentarios en mi código :) Acerca de preg_match, no creo que sea excesivo. Ya sabes, es algo simple para este caso. Incluso tengo la intención de que la expresión regular sea más compleja en el futuro. :) Gracias por tu comentario hermano! –

0

Este es un truco que funciona, aunque un poco lento. En un servidor con 0.6 millones de claves, tomó medio segundo completarlo.

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