.. /

Multi Get в Memcache

#memcached

Memcache предоставляет возможность получения значений нескольких ключей сразу. Зачем это может понадобиться и в каких случаях это нужно использовать? Посмотрим на структуру запросов от приложения к Memcache, когда идет получение нескольких ключей: Memcache get

Запрос к каждому ключу — это отдельный сетевой запрос:

  • Отправка из приложения в Memcache запроса с названием ключа
  • Отправка из Memcache в приложение ответа со значением ключа

Когда количество таких запросов переваливает за десятки с одной страницы Web сайта, следует подумать об оптимизации. Обычная функция memcache_get() позволяет передавать в параметры не один ключ, а массив ключей. Этот режим называется Multi Get. Тогда на сервер кэширования будет отправлен только один запрос и получен только один ответ с массивом значений: Memcache multi get

Использование

Рассмотрим небольшой пример. Пусть у нас есть список новостей. Каждая новость будет храниться в ключе под именем "news_item_[id]", где [id] — ID новости. Используя Multi Get мы сможем получить все новости за один запрос вместо нескольких десятков. Для этого достаточно передать массив ключей в функцию memcache_get() (либо метод get()): <? # Получаем список ID новостей (например, из базы данных) $news_ids = [1, 2, 3, 4, 5]; $m = new Memcache; foreach ( $news_ids as $id ) $keys[] = 'news_item_' . $id; $news = $m->get($keys);

# Переменная $keys содержит список ключей, в переменную $news попадет список данных новостей

Производительность

Сравним скорость Multi GET и обычного memcache_get() для каждого ключа. Скрипт для сравнения на PHP: <? $tests = 15000; $m = new Memcache; $m->connect('localhost', '11211'); for ( $i = 0; $i < $tests; $i ++ ) { $m->set('test' . $i, md5($i)); } $t = microtime(true); for ( $i = 0; $i < $tests; $i ++ ) { $list_get[] = $m->get('test' . $i); $keys[] = 'test' . $i; } echo 'Fetched ' . $tests . ' objects with standard get in ' . (microtime(true) - $t) . 's'; echo "\n"; $t = microtime(true); $list_mget = $m->get($keys); echo 'Fetched ' . $tests . ' objects with multiple get in ' . (microtime(true) - $t) . 's'; echo "\n";

# Отправим 15000 запросов одним запросом и несколькими

Результаты будут приблизительно такими:

Fetched 15000 objects with standard get in 0.47441411018372s
Fetched 15000 objects with multiple get in 0.023789882659912s

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

Когда следует применять Multi Get?

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

Перебор списков

Как в примере с новостям, логика Web приложения часто содержит перебор списков пользователей, картинок, новостей, комментариев и т.п. В этом случае Multi Get будет очень полезен и прост в реализации. Нужно отметить, что на практике необходимо дополнительно проверять наличие значений в возвращаемых ключах, т.к. каких-то значений может не быть: <? $news_ids = [1, 2, 3, 4, 5]; $m = new Memcache; foreach ( $news_ids as $id ) $keys[] = 'news_item_' . $id; $news = $m->get($keys); foreach ( $news as $i => $post ) { if ( !$post ) $post = get_post( $keys[$i] ); echo $post['title'] . '<br/>'; }

# Функция get_post() должна вернуть данные новости из базы данных

Cron задачи

В отдельной Cron задаче намного проще собрать необходимые для выборки ключи, чем в целом приложении. Их можно собирать и обрабатывать частями, например по 10 штук. Популярный пример — рассылка новостей по почте: <? $users_ids = [1, 2, 3, 4, 5, ...]; foreach ( $users_ids as $i => $id ) { if ( count($keys) < 10 ) { # собираем список ключей по 10 штук максимум $keys[] = 'user' . $id; # продолжаем, только если еще не конец списка if ( $keys[$i+1] ) continue; } # получаем данные пользователей $users = $m->get($keys); foreach ( $users as $user ) { mail($user['email'], 'Э', 'Чо'); } # очищаем массив ключей $keys = []; }

# Получаем сразу по 10 значений данных пользователей вместо одного

Самое важное

Использование множественного запроса Multi Get в Memcache позволяет снизить количество обращений от приложения к серверу кэша. Это уменьшает сетевой трафик и ускоряет работу приложения.

Подписаться   Следующий материал  


Зайти