Multi Get в Memcache
Memcache предоставляет возможность получения значений нескольких ключей сразу. Зачем это может понадобиться и в каких случаях это нужно использовать? Посмотрим на структуру запросов от приложения к Memcache, когда идет получение нескольких ключей:
Запрос к каждому ключу — это отдельный сетевой запрос:
- Отправка из приложения в Memcache запроса с названием ключа
- Отправка из Memcache в приложение ответа со значением ключа
Когда количество таких запросов переваливает за десятки с одной страницы Web сайта, следует подумать об оптимизации. Обычная функция memcache_get() позволяет передавать в параметры не один ключ, а массив ключей. Этот режим называется 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";
Отправим 15 тысяч запросов одним запросом и несколькими
Результаты будут приблизительно такими:
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 позволяет снизить количество обращений от приложения к серверу кэша. Это уменьшает сетевой трафик и ускоряет работу приложения.
Этот текст был написан несколько лет назад. С тех пор упомянутые здесь инструменты и софт могли получить обновления. Пожалуйста, проверяйте их актуальность.



Сообщить об опечатке
Текст, который будет отправлен нашим редакторам: