Par exemple, j'ai des éléments en cache avec le même préfixe, tels que
'app_111111', 'app_222222', 'app_333333', ...
Puis-je supprimer ces éléments 'app_xxxxxx' à l'aide de commandes memcached?
Memcached n'offre pas cette fonctionnalité par défaut, vous devez donc la construire vous-même.
Pour résoudre ce problème, vous devez définir un préfixe (ou un espace de nom) dans mon application pour les groupes de clés. Toute clé que je mets dans memcached a ce préfixe avant elle. Chaque fois que je veux "supprimer" des trucs de Memcached, je change juste le préfixe. Et chaque fois que je veux rechercher une clé dans Memcached, j'y ajoute ce préfixe.
Dans votre cas, vous pouvez commencer par définir le préfixe sur, par exemple, MyAppPrefix1
, afin que vos clés soient stockées sous la forme MyAppPrefix1::app_333333
, MyAppPrefix1::app_444444
.
Plus tard, lorsque vous souhaitez "supprimer" ces entrées, configurez votre application pour utiliser MyAppPrefix2
. Ensuite, lorsque vous essayez d’obtenir une clé de Memcached appelée app_333333
, elle recherchera MyAppPrefix2::app_333333
et ne la trouvera pas la première fois, comme si elle avait été supprimée.
Que diriez-vous de cette fonction 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;
}
Supprime les clés commençant par $ préfixe et retourne une liste de toutes les clés supprimées. Je l'ai utilisé sur plus de 30 000 clés tout à l'heure sur un serveur partagé et ce fut assez rapide - probablement moins d'une seconde.
Nous ne pouvons pas le faire en une seule requête à memcache. Nous pouvons juste faire ceci:
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);
}
}
}
}
}
}
}
}
}
}
Et appelez cette fonction comme ceci:
$prefixes = array();
array_Push($prefixes, 'prefix1_');
array_Push($prefixes, 'prefix2_');
array_Push($prefixes, 'prefix3_');
$this->clearByPrefix($prefixes);
C'est un hack qui fonctionne, bien qu'un peu lent. Sur un serveur avec 0,6 million de clés, l’opération a pris une demi-seconde.
$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));
}
}