2012-05-29 6 views

risposta

36

Memcached non offre questa funzionalità fuori dalla scatola, quindi è necessario crearla da solo.

Il modo in cui risolvo questo è definendo un prefisso (o spazio dei nomi) nella mia applicazione per gruppi di chiavi. Qualsiasi chiave che imposto in memcached ha quel prefisso prima di esso. Ogni volta che voglio "cancellare" cose da Memcached, cambio semplicemente il prefisso. E ogni volta che voglio cercare una chiave in Memcached, aggiungo quel prefisso ad esso.

Nel tuo caso, puoi iniziare impostando il prefisso, ad esempio, MyAppPrefix1, in modo che le chiavi vengano memorizzate come MyAppPrefix1::app_333333, MyAppPrefix1::app_444444.

Successivamente, quando si desidera "cancellare" queste voci, impostare la propria applicazione su MyAppPrefix2. Quindi, quando provi a ottenere una chiave da Memcached chiamata app_333333, cercherà MyAppPrefix2::app_333333 e non la troverà la prima volta, come se fosse stata eliminata.

+1

E come si fa a cancellare le vecchie voci? per scadenza? –

+0

@ AlfonsoFernandez-Ocampo si, perché no? Memcache li cancellerà quando necessario – yefrem

+0

che sembra eccellente, ma Memcached cancellerà dopo la scadenza o quando sta per essere pieno? – kscius

4

Che ne dite di questa funzione in 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 le chiavi che iniziano con $ prefisso e restituisce un elenco di tutte le chiavi rimosse. L'ho eseguito su più di 30.000 chiavi solo ora su un server condiviso ed è stato piuttosto veloce, probabilmente meno di un secondo.

+2

Non è garantito che funzioni. http://php.net/manual/en/memcached.getallkeys.php "Come memcache non garantisce di restituire tutte le chiavi che, inoltre, non può assumere che tutte le chiavi sono stati restituiti." –

+2

Grazie per la segnalazione @TimMartens. Suppongo che sia buono come si può ottenere? Mi piacerebbe che ci fossero un po 'più di informazioni su quando e perché il metodo 'getAllKeys()' rischia di venire a breve .. puoi far luce su questo? I documenti sono piuttosto inutili. – billynoah

0

Non possiamo farlo in una sola richiesta di memcache. Abbiamo appena può fare questo:

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

e chiamare questa funzione come questa:

 $prefixes = array(); 

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

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

Anche se il tuo codice sembra facile da capire, potresti spiegare che cosa fa e perché credi che questa soluzione aiuti il ​​richiedente. A proposito, preg_match quando puoi semplicemente chiamare strpos, è davvero un eccesso. –

+0

Forse dovrei aggiungere altri commenti nel mio codice :) Riguardo a preg_match, non penso che sia eccessivo. Sai, è solo una cosa semplice per questo caso. Intendo anche che la regex sarà più complessa in futuro. :) Grazie per il tuo commento bro! –

0

Si tratta di un hack che funziona, anche se un po 'lento. Su un server con 0,6 milioni di chiavi, ci sono voluti mezzo secondo per completare.

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