Подтвердить что ты не робот

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

Например, у меня есть некоторые кешированные элементы с одним и тем же префиксом, например

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

Можно ли удалить такие элементы "app_xxxxxx" любыми командами memcached?

4b9b3361

Ответ 1

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

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

В вашем случае вы можете начать с установки префикса до, скажем, MyAppPrefix1, поэтому ваши ключи будут сохранены как MyAppPrefix1::app_333333, MyAppPrefix1::app_444444.

Позже, когда вы хотите "удалить" эти записи, установите приложение для использования MyAppPrefix2. Затем, когда вы пытаетесь получить ключ от Memcached с именем app_333333, он будет искать MyAppPrefix2::app_333333 и не найдет его в первый раз, как если бы он был удален.

Ответ 2

Как насчет этой функции в 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 + ключей только сейчас на общем сервере, и это было довольно быстро - возможно, менее одной секунды.

Ответ 3

Мы не можем сделать это только в одном запросе 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);

Ответ 4

Это взлом, который работает, хотя и немного медленный. На сервере с 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));
        }
    }