Конвейер Redis, работающий с промахами в кеше

Я пытаюсь найти лучший способ реализовать конвейерную обработку Redis. Мы используем redis в качестве кеша поверх MySQL для хранения пользовательских данных, списков продуктов и т. Д. Я использую это в качестве отправной точки: https://joshtronic.com/2014/06/08/how-to-pipeline-with-phpredis/

Мой вопрос: если у вас есть правильно отсортированный массив идентификаторов. Вы просматриваете конвейер Redis следующим образом:

$redis = new Redis();

// Opens up the pipeline
$pipe = $redis->multi(Redis::PIPELINE);

// Loops through the data and performs actions
foreach ($users as $user_id => $username)
{
    // Increment the number of times the user record has been accessed
    $pipe->incr('accessed:' . $user_id);

    // Pulls the user record
    $pipe->get('user:' . $user_id);
}

// Executes all of the commands in one shot
$users = $pipe->exec();

Что происходит, когда $pipe->get('user:' . $user_id); недоступен, потому что он не запрашивался ранее или был удален Redis и т. Д.? Предполагая, что это результат № 13 из 50, как мы а) узнаем, что мы не смогли получить этот объект и б) правильно отсортировали массив пользователей?

Спасибо


person StackOverflowed    schedule 31.05.2017    source источник


Ответы (1)


Отвечу на вопрос, касающийся протокола Redis. То, как это работает на конкретном языке, в этом случае более или менее одинаково.

Прежде всего, давайте проверим, как работает конвейер Redis: это просто способ отправить несколько команд на сервер, выполнить их и получить несколько ответов. В этом нет ничего особенного, вы просто получаете массив с ответами на каждую команду в конвейере.

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

Подробнее о конвейерной обработке можно узнать здесь: https://redis.io/topics/pipelining. Еще одно замечание, поскольку каждый конвейерный пакет работает бесперебойно (с точки зрения Redis), имеет смысл отправлять эти команды просматриваемыми фрагментами, то есть не отправлять 100 тыс. Команд в одном конвейере, что может заблокировать Redis на длительный период времени, разделите их на блоки по 1 или 10 тыс. команд.

В вашем случае вы запускаете в цикле следующий фрагмент:

// Increment the number of times the user record has been accessed
$pipe->incr('accessed:' . $user_id);

// Pulls the user record
$pipe->get('user:' . $user_id);

Вопрос в том, что вводится в конвейер? Допустим, вы хотите обновить данные для u1, u2, u3, u4 как идентификаторы пользователей. Таким образом, конвейер с командами Redis будет выглядеть так:

INCR accessed:u1
GET user:u1
INCR accessed:u2
GET user:u2
INCR accessed:u3
GET user:u3
INCR accessed:u4
GET user:u4

Скажем:

  • К u1 раньше обращались 100 раз,
  • К u2 раньше обращались 5 раз,
  • u3 ранее не использовался и
  • u4 и сопутствующих данных не существует.

В этом случае результатом будет массив ответов Redis, содержащий:

101
u1 string data stored at user:u1
6
u2 string data stored at user:u2
1
u3 string data stored at user:u3
1
NIL

Как видите, Redis будет рассматривать отсутствующие значения INCR как 0 и выполнять incr(0). Наконец, Redis ничего не сортирует, и результаты появятся в запросе в соответствии с запросом.

Привязка к языку, например Драйвер Redis просто проанализирует этот протокол и предоставит представление проанализированным данным. Без сохранения набора команд драйвер Redis не сможет правильно работать, а вам, как программисту, будет невозможно что-то сделать. Просто имейте в виду, что этот запрос не дублируется в ответе, т.е. вы не получите ключ для u1 или u2 при выполнении GET, а только данные для этого ключа. Таким образом, ваша реализация должна помнить, что в позиции 1 (индекс, отсчитываемый от нуля) появляется результат GET для u1.

person ovanes    schedule 31.05.2017