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

Проверьте, существует ли ключ в Memcache

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

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

Спасибо.

4b9b3361

Ответ 1

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

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

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

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

Memcache::delete  (  string $key)

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

Ответ 2

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

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

    return \Memcached::RES_NOTFOUND !== $m->getResultCode();
}

Ответ 3

В основном, что вы хотите сделать, это заполнить memcached вашими данными, не так ли?

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

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

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

Ответ 4

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

Ответ 5

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

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

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

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

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

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

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

Ответ 6

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

Ответ 7

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 для замены значения ничем, а потому, что единственное, что я использовал, - 0, я получил ошибку EXISTS.

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

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

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

Ответ 8

Это не имеет смысла с точки зрения Memcached. Если вы хотите избежать медленного источника данных (по плану, я полагаю?), Сохраните данные в более быстрый, но все же стабильный источник данных (например, файл) в запланированном задании. Когда вам нужны данные, попробуйте сначала прочитать Memcached, и если это не удается прочитать файл и сохранить его в Memcached.

Memcached не может дать вам хороший ответ, так как pakore уже ответил. Архитектура не предназначена для стабильного источника данных.

Ответ 9

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

(bool) Memcache::get(string $key)

Ответ 10

(немного поздно для обсуждения, но) на самом деле вы можете получить доступ ко всем ключам/значениям, хранящимся в 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)

Ответ 11

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

Вот что я закончил.

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

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