На сегодняшний день время отклика на запрос является критичной метрикой для любого проекта. Пользователи не очень любят, когда web-страница формируется долго (несколько секунд или дольше). Поэтому разработчики стремятся уменьшить время ответа на запрос клиента, для чего прибегают к кэшированию.
Представим, что разрабатывается торговая платформа и есть личный кабинет с аналитикой сделок пользователя. Нужно выводить количество сделок, прибыль, средний оборот и тд. Большинство метрик являются агрегационными, то есть их нужно высчитывать. Если использовать только РСУБД, то среднее время ответа будет сотни миллисекунд, а при большой нагрузке — секунды. Можно подключить подходящие аналитические базы данных, но чаще всего это слишком дорого в средних проектах.
Самая распространенная практика решения сегодня — это кэш. Сложные вычисления кэшируются, то есть записываются в оперативную память. Обращение к оперативной памяти займет сотни наносекунд, примерно в миллион раз быстрее, чем вычислить данные из РСУБД. Новая схема взаимодействия будет включать кэширующий сервер. Алгоритм следующий:
Как у любого решения в разработке, кэширование — не серебряная пуля и имеет свои недостатки. Несколько моментов, которые стоит держать в уме при использовании кэша:
Redis чаще всего используют именно как кэширующий сервер. Он имеет богатый встроенный функционал для этих целей. Рассмотрим основные команды, с помощью которых кэшируют значения в Redis.
Представим, что нужно записать количество сделок пользователя в кэш. Запишем, что у пользователя с ID 33 имеется 5 сделок. Используем обычную команду set
:
127.0.0.1:6379> set user:33:deals_count 5
OK
Данные записаны. Однако они будут храниться вечно до следующей перезагрузки сервера или пока не будут удалены вручную. Одно из основных свойств кэша — это то, что он хранится короткий промежуток времени. Данных может быть много, а ресурсы серверов не бесконечны. К счастью в Redis можно указать время жизни ключа (время экспирации), по истечении которого ключ будет удален. Для этого достаточно добавить постфикс ex количество_секунд
к команде set
:
127.0.0.1:6379> set user:33:deals_count 5 ex 120
OK
Проверить, через сколько ключ удалится можно командой ttl
:
127.0.0.1:6379> ttl user:33:deals_count
(integer) 115
В данном случае ключ user:33:deals_count исчезнет через 115 секунд.
Если попытаться получить значение спустя это время, то вернется пустой ответ:
127.0.0.1:6379> get user:33:deals_count
(nil)
Время жизни можно задавать не только в секундах, но и в миллисекундах с помощью префикса px количество_миллисекунд
:
set user:33:deals_count 5 px 10000
Проверка времени жизни осуществляется командой pttl
:
127.0.0.1:6379> pttl user:33:deals_count
(integer) 7484
Вывод выше показывает, что ключ user:33:deals_count исчезнет через 7484 миллисекунд (~7.4 секунд).
Любой кэш может стать неактуальным раньше времени жизни. В нашем примере со сделками это может произойти при возникновении новой сделки у пользователя. В этом случае нужно удалить ключ в кэше, чтобы при следующем запросе произошел пересчет значения. Может возникнуть вопрос: а почему бы просто не добавить значение в имеющийся ключ? В данном примере это было бы наилучшим решением, но действовать необходимо не «в лоб». При увеличении значения двумя командами get
+ set
может получиться неконсистентное состояние (подробнее эта проблема будет рассмотрена в следующем уроке). Также обновление значения не всегда возможно, например, в случае если значение — это среднее арифметическое.
Удаление ключа происходит командой del
:
127.0.0.1:6379> del user:33:deals_count
(integer) 1
Вернувшееся значение 1 означает, что ключ существовал и был успешно удален. Если ключа не было, то вернулся бы 0.
Иногда требуется удалить тысячи ключей за раз. Например, у поставщика цен на акции произошел сбой и все сделки за период сбоя оказались недействительными. В этом случае нельзя использовать N вызовов команды del
, потому что это будет выполняться очень долго и заберет все ресурсы Redis. Для множественного удаления существует команда unlink
, которую можно безопасно использовать в продакшен-среде:
127.0.0.1:6379> unlink user:1:deals_count user:2:deals_count user:3:deals_count
(integer) 1
Все ключи для удаления указываются через пробел. Стоит учитывать, что ключи удаляются асинхронно, то есть могут существовать после unlink
короткий промежуток времени.
set ключ значение ex количество_секунд
, а в миллисекундах командой set ключ значение px количество_миллисекунд
del ключ
. Для удаления множества ключей существует команда unlink ключ1 ключ2 ...
Вам ответят команда поддержки Хекслета или другие студенты.
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
Наши выпускники работают в компаниях:
Зарегистрируйтесь или войдите в свой аккаунт
Задавайте вопросы, если хотите обсудить теорию или упражнения. Команда поддержки Хекслета и опытные участники сообщества помогут найти ответы и решить задачу