Например, у меня есть некоторые кешированные элементы с одним и тем же префиксом, например
'app_111111', 'app_222222', 'app_333333', ...
Можно ли удалить такие элементы "app_xxxxxx" любыми командами memcached?
Например, у меня есть некоторые кешированные элементы с одним и тем же префиксом, например
'app_111111', 'app_222222', 'app_333333', ...
Можно ли удалить такие элементы "app_xxxxxx" любыми командами memcached?
Memcached не предлагает эту функциональность из коробки, поэтому вам нужно ее самостоятельно создать.
Способ, которым я решаю это, - определить префикс (или пространство имен) в моем приложении для групп ключей. Любой ключ, который я установил в memcached, имеет этот префикс перед ним. Всякий раз, когда я хочу "удалить" материал из Memcached, я просто изменяю префикс. И всякий раз, когда я хочу найти ключ в Memcached, я добавляю к нему этот префикс.
В вашем случае вы можете начать с установки префикса до, скажем, MyAppPrefix1
, поэтому ваши ключи будут сохранены как MyAppPrefix1::app_333333
, MyAppPrefix1::app_444444
.
Позже, когда вы хотите "удалить" эти записи, установите приложение для использования MyAppPrefix2
. Затем, когда вы пытаетесь получить ключ от Memcached с именем app_333333
, он будет искать MyAppPrefix2::app_333333
и не найдет его в первый раз, как если бы он был удален.
Как насчет этой функции в 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 + ключей только сейчас на общем сервере, и это было довольно быстро - возможно, менее одной секунды.
Мы не можем сделать это только в одном запросе 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,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));
}
}