Проверьте, существует ли ключ в Memcache - PullRequest
18 голосов
/ 22 июня 2010

Как проверить в PHP, хранится ли значение в Memcache, не извлекая его?Мне не нравится извлекать его, потому что все значения, которые я установил, имеют размер 1 МБ, и после того, как я их получу, я их не использую, поэтому я трачу ресурсы.Я использую это в скрипте, который проверяет, кэшированы ли определенные ключи в memcache, а если нет, он читает их из медленного источника данных и устанавливает их в memcache.

Редактировать: Что делать, если я использую Memcached::appendдобавить NULL к ключу, который я проверяю?Возвращает TRUE в случае успеха или FALSE в случае ошибки.Memcached::getResultCode вернет Memcached::RES_NOTSTORED, если ключ не существует.Таким образом, я проверяю, существует ли ключ, и он должен поставить ключ в верхнюю часть списка LRU, верно?

Спасибо.

Ответы [ 11 ]

6 голосов
/ 22 июня 2010

Я не уверен, поможет ли это вам, но вы можете использовать

Memcache::add  (  string $key  ,  mixed $var)

Он вернет false, если ключ уже существует.

В случае возврата true вы можете использовать

Memcache::delete  (  string $key)

чтобы удалить ключ, который вы только что установили. Таким образом, вам не нужно будет извлекать данные.

6 голосов
/ 01 января 2015

Интересно, почему у Memcached нет специального метода для этого? Вот к чему я пришел после некоторых рассуждений:

function has($key)
{
    $m->get($key)

    return \Memcached::RES_NOTFOUND !== $m->getResultCode();
}
3 голосов
/ 22 июня 2010

Я решил это с помощью Memcached :: append. Я пытаюсь добавить значение NULL, и если оно возвращает TRUE, значит, ключ существует. Если он возвращает FALSE, это означает, что ключ не существует. Если ключ существует, он также помещается в начало списка LRU.

3 голосов
/ 22 июня 2010

По сути, вы хотите заполнить memcached вашими данными, верно?

Дело в том, что запрос о наличии ключа без получения значения не очень полезен.Смотрите этот сценарий:

Вы спрашиваете, существует ли ключ, и он существует.Сразу после запроса данные ключа удаляются из кеша.Пока ваш ответ возвращается, говоря, что дата уже есть, реальность такова, что данных там нет.Таким образом, вы потеряли время, спрашивая, потому что ответ отличается от реальности.

Полагаю, вы хотите спросить, существует ли ключ, а затем, если его нет, заполните его своими данными.Почему бы вам не заполнить все данные напрямую?Кстати, вы уже подумали, что, заполняя memcached данными, вы можете удалять ключи, которые вы только что вставили?

2 голосов
/ 21 мая 2012

Мне не нравится предложение добавить / удалить, потому что оно вставляет недействительные данные, от которых может зависеть ваше приложение. Если ваше приложение делает такое предположение, оно может вызвать незначительную ошибку, которая возникает очень часто из-за состояния гонки, которое оно вводит.

Одно из решений состоит в том, чтобы взглянуть на значение, и если его временные данные притворяются, что его там нет, но для этого потребуется, чтобы весь код приложения использовал один и тот же API, или вам нужно обновить само приложение, ни то, ни другое несколько подвержен ошибкам из-за дополнительной сложности.

Если набор ключей достаточно мал, вы можете сохранить его в memcached и использовать, чтобы определить, следует ли снова получать данные из источника. Однако, если оно больше или больше, чем значение, этот метод хуже, чем просто получить все значение из memcached.

Затем вы можете решить новую проблему, используя индекс для разделения ключей на меньшие наборы (конечно, хороший способ разделить эти данные, чтобы каждый сегмент определенного размера легче сказать, чем сделать).

Реализация будет состоять из использования memcached append или prepend для поддержания вашего списка ключей, привязанного к некоторому мастер-ключу или мастер-ключу, который указывает на набор sub_keys, которые указывают на сами ключи:)

В любом случае вы делаете приложение все более и более сложным, поэтому я бы рекомендовал делать это только в том случае, если действительно существует узкое место (как это было бы, если бы необходимо часто проверять наличие ключей в сети), или если юзабилити в концерне (латентность).

В моем случае я не буду этого делать, потому что я собираюсь обращаться к memcached только через localhost и использую его как расширение своего приложения для кэширования ресурсов, для нормальной загрузки которых требуется более нескольких секунд.

1 голос
/ 08 мая 2017

memcached теперь имеет команду cas. Вы можете использовать его с уникальным cas как 0, чтобы получить ответы EXISTS или NOT_FOUND:

$ telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
set hello 0 0 5
12345
STORED
gets hello
VALUE hello 0 5 6743
12345
END
cas hello 0 0 0 0

EXISTS
cas foo 0 0 0 0 

NOT_FOUND

В приведенной выше расшифровке я сначала использую команду set, чтобы установить приветный ключ со значением 12345. Затем возвращает его, что также возвращает уникальный 6743. Затем я пытаюсь использовать команду cas, чтобы заменить значение ничем, но поскольку уникальность cas, которую я использовал, равна 0, я получил ошибку EXISTS.

Наконец, я пытаюсь использовать cas, чтобы установить несуществующий ключ foo и получить ошибку NOT_FOUND.

Поскольку memcached использует глобальное значение приращения для уникальности cas, использование 0 безопасно, так как оно недопустимо для элемента, который вы пытаетесь установить, и вы получите ошибку EXISTS, если она существует.

Извините, не знаком с клиентом php memcache, чтобы поместить его в код php.

1 голос
/ 15 декабря 2012

Просто невозможно, невозможно проверить, существует только ключ или нет.Лучше создать отдельный ключ со значениями true / false, чтобы проверить наличие ключей

0 голосов
/ 08 января 2018

Мне нужен был надежный тест, чтобы знать, использовать ли memcache Set или замену memcache.

Это то, что я закончил.

Другой вариант - настроить сетевой сокет для запроса memcache, но в конце концов он будет выполнять то же самое, и это соединение уже существует, что избавляет меня от необходимости устанавливать и поддерживать другое соединение, как вОтвет Джоэля Чена.

$key = 'test';
$value = 'foobarbaz';
/**
 * Intricate dance to test if key exists.
 * If it doesn't exist flags will remain a boolean and we need to use the method set.
 * If it does exist it'll be set to integer indicating the compression and what not, then we need to use replace.
 */
$storageFlag = (is_null($value) || is_bool($value) || is_int($value) || is_float($value) ? false : MEMCACHE_COMPRESSED);
$flags = false;
$memcache->get($key, $flags);
if(false === $flags) {
    $memcache->set($key, $value, storageFlag  , $minutes);
}
else {
    $memcache->replace($key, $value, storageFlag, $minutes);
}

Теперь, если у вас есть «большие данные», решение довольно простое.Используйте второй ключ в cojoin, который содержит что-то простое, например, целое число для проверки.Всегда используйте их вместе, и у вас нет проблем.

$key = 'test';
$value = 'foobarbaz';

$storageFlag = (is_null($value) || is_bool($value) || is_int($value) || is_float($value) ? false : MEMCACHE_COMPRESSED);
$flags = false;
$exist_key = $key.'_exists';

$memcache->get($exist_key, $flags);
if(false === $flags) {
    $memcache->set($key, $value, storageFlag  , $minutes);
    $memcache->set($exist_key, 42, false  , $minutes);
}
else {
    $memcache->replace($key, $value, storageFlag, $minutes);
    $memcache->replace($exist_key, 42, false  , $minutes);
}
0 голосов
/ 20 ноября 2014

(немного поздно для обсуждения, но) на самом деле вы можете получить доступ ко всем ключам / значениям, хранящимся в memcache, за:

$allSlabs = $memcache->getExtendedStats('slabs');
$items = $memcache->getExtendedStats('items');

foreach ($allSlabs as $server => $slabs)
   foreach ($slabs as $slabId => $slabMeta)
       foreach ($memcache->getExtendedStats('cachedump', (int) $slabId) as $entries)
           if (!empty($entries))
               foreach ($entries as $key => $entry)
0 голосов
/ 20 октября 2012

Самый простой способ - получить данный ключ и привести его к логическому значению.

(bool) Memcache::get(string $key)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...