Multi Get в Memcache

admin

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 позволяет снизить количество обращений от приложения к серверу кэша. Это уменьшает сетевой трафик и ускоряет работу приложения.

Этот текст был написан несколько лет назад. С тех пор упомянутые здесь инструменты и софт могли получить обновления. Пожалуйста, проверяйте их актуальность.

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

Переписки, фото, история браузера: киевский программист зарабатывал на шпионаже

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023