Чтобы сайт или приложение загружались максимально быстро, данные рекомендуется кэшировать в оперативную память сервера. Сегодня рассмотрим вариант создания кэша с помощью Redis и Memcached.
1102 открытий705 показов
Чем, в первую очередь, руководствуются пользователи, открывая ваш сайт или запуская мобильное приложение? Правильно, скоростью работы! Если страница не загрузится за пару секунд, большинство посетителей просто закроет ее и уйдет к конкурентам.
Чтобы основные данные загружались максимально быстро, их рекомендуется кэшировать в оперативную память сервера или использовать кэширование на пользовательское устройство. Сегодня рассмотрим вариант создания кэша на сервере с помощью Redis и Memcached.
Что такое Redis и Memcached
Разберемся, что представляют из себя обе системы и перечислим их основные различия.
Краткий обзор Redis: структура данных, поддержка персистентности, возможности
Redis — это популярная key-value система хранения данных в оперативной памяти. Она позволяет работать с большим количеством типов данных, среди них списки и множества, битовые массивы, гео-координаты и другие.
Как выучить Python бесплатноtproger.ru
Redis нельзя назвать полноценной СУБД, однако его возможностей достаточно для того, чтобы загружать данные из основной базы данных в кэш, получать и передавать информацию, взаимодействовать с пользователем и оперативно реагировать на все запросы. Для Redis доступно несколько вариантов отказоустойчивых конфигураций и подходов, в том числе кластеризация и шардирование.
Для обеспечения персистентности данных Redis выгружает слепки на жесткий диск сервера, однако этот процесс может требовать больших ресурсов системы и занимать редис-сервер на продолжительное время из-за атомарности выполнения операций.
Краткий обзор Memcached: легковесное кэширование в памяти, простота и высокая скорость
Memcached — это сервис кэширования данных в оперативную память, созданный в далеком 2003 году. Большой плюс этого сервиса в том, что скорость его работы не зависит от количества хранимых в кэше данных, а интерфейс максимально прост. Однако есть и существенное ограничение: Memcached позволяет хранить лишь данные типа set.
Основные различия между Redis и Memcached
Сравнивая две системы, в первую очередь еще раз отметим отличия в хранимых данных: серверы Redis поддерживают несколько типов данных, тогда как Memcached способен хранить лишь множества (set). Redis умеет сохранять слепки данных на жесткий диск, для него доступна LRU-политика удаления данных и полное отключение функции освобождения места. А также, в отличие от Memcached, этот сервис поддерживает master-slave репликацию и подходит для создания очередей сообщений.
Настройка Redis для кэширования
Далее разберемся с тем, как установить Redis, задать ему базовые настройки и использовать key-value систему, запуская кэширование базы данных.
Установка Redis и базовая конфигурация
Так как Redis создан для Unix-подобных систем, его установка на Windows Server возможна только через wsl. Когда в вашем распоряжении есть сервер, например, на Ubuntu, установить Redis можно через apt
или apt-get
.
sudo apt update - y sudo apt upgrade - y sudo apt install redis-server
Для проверки успешной установки можно запустить пинг сервера Redis через redis-cli
:
redis-cli ping
Фактически, система доступна для использования уже на этом этапе, однако рекомендуется изменить некоторые настройки для повышения ее безопасности. Изменения вносятся в файл конфигурации:
sudo nano/etc/redis/redis.conf
Можно изменить порт — по умолчанию Redis функционирует на 6379 — дать доступ по сети и задать пароль администратора. Для этого меняем bind 127.0.0.1 -:: 1 на bind 0.0.0.0, раскомментируем строку requirepass и в ней прописываем сам пароль. Например: requirepass averyVERYlongPASSword72349.
После внесения изменения перезапускаем Redis-server:
sudo service redis-server restart
Как использовать Redis для кэширования типа ключ-значение
Благодаря тому, что Redis — достаточно универсальное in-memory хранилище, его можно использовать при кэшировании данных в формате ключ-значение в самых разных проектах. Он подойдет и для хранения API-запросов, и для пользовательских сессий, и для оптимизации работы с основными базами данных, например, Postgresql или MySQL. Каждому элементу в Redis присваивается собственный уникальный ключ, по нему в любой момент можно получить оперативный доступ, изменить или удалить запись. Максимальный объем данных в одной записи-значении — 512Mb.
В Redis доступны разные политики вытеснения, вы можете самостоятельно выбрать принцип, по которому сервер будет удалять ненужные данные при переполнении выделенной ему памяти. Паттерн кэширования также остается «на совести» разработчика.
🔥 Python, Go, Ruby — сайты создателей популярнейших языков собрали в одном местеtproger.ru
Если для сайта или приложения нужен кэш большого объема, применяется принцип холодного кэширования, когда данные загружаются на старте системы, а значит, находятся в Redis еще до прямого запроса от пользователя.
Примеры использования Redis с языками программирования (например, Python или Node.js)
Разберемся, как использовать Redis из Python, добавлять и удалять данные на примере работы с помощью клиента redis-py. Первым делом его нужно установить:
python -m pip install redis
Далее запишем в Redis данные и получим одну из записей по ключу.
Подключаемся к Redis.
import redis r = redis.Redis(host='localhost', port=6379, password=None)
Записываем данные.
r.mset({"One": "Eno", "Two": "Owt"})
Получаем запись по ключу “Two” и выводим с декодированием.
r.get("Two").decode("utf-8") print Two
Видим в консоли:
b'Two'
Для удаления используем команду delete.
r.delete("One")
Подробности по использованию redis-py можно найти в официальной документации: этот клиент активно поддерживается и пользуется популярностью у разработчиков.
Настройка Memcached для кэширования
Теперь перейдем к Memcached: разберемся, как его установить и настроить, и поймем, какие ограничения имеются у этого сервиса.
Установка и настройка Memcached
Установка Memcached мало отличается от любого другого сервиса, для нее используется пакетный менеджер. В Ubuntu и Debian — apt
, в CentOS или Fedora — yum
. Для примера, установка на Ubuntu будет выглядеть так:
sudo apt install memcached
По-умолчанию используется порт 11211, но его можно изменить в файле конфигурации /etc/memcached.conf. Основные параметры заданы буквенными ключами, для некоторых задать дополнительные настройки:
- logfile/var/log/memcached.log
- -v и -vv – подробный и очень подробный режимы вывода информации
- -m – доступный максимум оперативной памяти, по-умолчанию 64Мб
- -u – системный пользователь, от имени которого запущен сервис
- -l 127.0.0.1 – IP-адрес, на котором Memcached будет ожидать соединения. По-умолчанию сервис недоступен по сети
- -p – порт
- -с – допустимое количество одновременных подключений
- -P /var/run/memcached/memcached.pid
После внесения изменения в файл настроек Memcached необходимо перезапустить:
service memcached restart
Принцип работы с ключ-значение в Memcached
Структура Memcached похожа на структуру хранения данных в Redis: каждому значению value присваивается уникальный ключ key. В value может храниться строка или бинарные данные.
Для внесения записи в базу достаточно воспользоваться командой <имя ключа> <флаги (можно оставить 0)> <время хранения в секундах (0 – вечно)> <объем памяти в байтах, зарезервированный для хранения значения>:
add uni_key 0 0 8
После введения этой команды в строку терминала можно ввести значение для хранения.
Для получения данных используется команда get
<ключ>, для удаления — delete
<key>.
Однако все эти нативные команды используются достаточно редко, так как каждый популярный язык программирования содержит собственные методы и клиенты для работы с Memcached.
Примеры использования Memcached с популярными языками программирования.
Посмотрим, как обращаться к Memcached с помощью Python и какие основные команды можно выполнить.
Для начала установим библиотеку, например, pymemcache:
pip install pymemcache
Подключимся к запущенному серверу Memcached, создадим запись, внесем и получим данные.
from pymemcache.client import base client = base.Client((“localhost”, 11211)) client.set(“key”, «value”) client.get(“key”)
Ниже показан код, который позволит проверить наличие записи в Memcached, и при ее отсутствии запустит функцию updating_key. Предположим, что она задана заранее и получает нужное значение из основной БД.
result = client.get(“key1”) if result is None: # такого ключа у нас нет result = updating_key() # записываем полученное значение с нужным ключом в Memcached client.set(“key1”, result)
Также можно удалить запись по ключу при помощи delete:
client.delete ("key")
Операции set
, get
и delete
— основные способы взаимодействия с memcached из Python, они позволят создавать кэш и пользоваться им по мере необходимости.
Сравнение Redis и Memcached
Для типовых задач кэширования на большинстве проектов подходят оба решения. Однако каждое из них имеет свои особенности, бонусы и недостатки.
Производительность: сравнение скорости работы Redis и Memcached
Считается, что Memcached — самый быстрый сервис, который можно использовать при кэшировании. Однако на практике его производительность и скорость работы на запись вполне сравнимы с Redis. На запись миллиона ключей Memcached тратит около трех миллисекунд, Redis — около 15-ти. А операция считывания данных и вовсе выводит вперед Redis, в котором время практически не растет с ростом числа считываемых ключей, тогда как у Memcached возрастает, пусть и незначительно.
Гибкость данных: поддерживаемые типы данных в Redis и ограничение Memcached
По параметру «количество поддерживаемых типов данных» Redis обходит Memcached на голову, поскольку последний умеет хранить лишь строковые и бинарные значения. А с помощью Redis можно кэшировать помимо этих двух типов еще и списки, множества, упорядоченные множества, битовые поля и геопространственные данные.
Не будем забывать и об ограничениях Memcached, в котором длина ключа ограничена 250 байтами, а размер значения не может превышать 1 Мб по-умолчанию и 128 Мб — при внесении изменений в настройки.
Персистентность данных: плюсы и минусы каждого решения
В описании Redis мы уже упоминали о том, что он умеет записывать данные на жесткий диск. С одной стороны, это обеспечивает их сохранность, с другой занимает ресурсы сервера. Редис — однопоточная система с атомарным выполнением операций, а значит, выгрузка большого слепка данных на диск блокирует все остальные процессы. Для борьбы с этим существует несколько способов, в том числе запуск Redis cluster и разбиение задачи выгрузки данных в Redis на несколько небольших пакетов.
В отличие от Redis, Memcached вовсе не является персистентным хранилищем и в нем отсутствуют функции для обеспечения сохранности данных. То есть после ребута сервер начинает работать с пустым кэшем и после сбоя Memcached все данные в нем будут потеряны.
Когда использовать Redis и когда Memcached для конкретных задач.
Говоря о конкретных случаях использования того или иного решения, можно точно сказать, что выбор остается за разработчиком. Но если в небольшом приложении нужно кэшировать простые строковые данные, а сброс кэша в случае перезагрузки сервера не является чем-то критичным, то отлично подойдет Memcached. Для более сложных ситуаций с хранением разных типов данных и необходимостью повышать отказоустойчивость, стоит отдать предпочтение Redis.
Например, для кэширования пользовательских сессий или результатов запросов к API больше подойдет Redis, а для выгрузки части информации из основной базы данных для ускорения доступа к ней достаточно будет и Memcached.
Примеры использования кэширования в реальных проектах
Лучше всего понять, в каких задачах разработчик сталкивается с необходимостью кэширования, помогут примеры из реальных проектов.
Кэширование результатов API запросов
Мало кто создает API просто так «для галочки». Разработчик обычно предполагает, что запросы в интерфейс будут достаточно многочисленными, а некоторые из них вполне могут повторяться. Или некоторые отчеты будут требовать довольно продолжительных вычислений.
В таких ситуациях для снижения нагрузки на основную БД и ускорения получения ответов от приложения пользуются кэшированием данных в RAM. Это позволит давать быстрый доступ к одним и тем же данным без постоянного подключения к основной базе. А холодный кэш, сформированный из результатов самых тяжелых отчетов, позволит пользователю не ждать их формирования, а получить данные сразу после отправки запроса.
Кэширование сессий пользователей
Пользовательские сессии — еще один повсеместно распространенный повод прибегнуть к кэшированию. Получение пользовательского токена от сервера авторизации — достаточно продолжительный процесс, и для того чтобы не повторять его при каждом запросе, токен часто хранят в кэше на пользовательском устройстве.
На стороне сервера в таком случае таблица с привилегиями для каждого токена может храниться в кэше Redis или Memcached, так проверка прав доступа будет происходить максимально быстро.
Кэширование баз данных и оптимизация запросов
Сервисами для кэширования пользуются и с целью хранения данных из основной БД. Кто-то загружает в кэш всю базу, кто-то — лишь ее наиболее часто используемую часть, но цели в обоих случаях совпадают. Во-первых, кэширование баз данных ускоряет процесс получения информации по запросу: RAM отдает данные гораздо быстрее. Во-вторых, позволяет снизить нагрузку на систему: при хранении части данных в оперативной памяти многие запросы проходят вовсе без обращения к жесткому диску.
Советы по оптимизации кэширования
Несмотря на всю прелесть использования Redis и Memcached, будем помнить о том, что не все кэширование одинаково полезно. Существует несколько деталей, на которые стоит обратить внимание при проектировании и создании кэша.
Выбор правильной стратегии кэширования (Lazy caching, Write-through, Write-back)
Одна из основных проблем кэширования — возможность того, что данные устареют и не обновятся вовремя. Для борьбы с этим недугом придумано несколько стратегий:
- Lazy caching или ленивый кэш. Такой кэш просто хранится без всяких проверок до тех пор, пока не устареет, и подходит для редко обновляемых данных. Политика устаревания настраивается для каждого случая индивидуально.
- Write-through cache или сквозной кэш. Изменение данный проходит «насквозь», задевая сразу и кэш, и основное хранилище.
- Write-back. В этом случае все изменения вносятся оперативно только в кэш, а в основное хранилище выгружаются по команде или с определенным интервалом.
- Синхронизированный кэш. При получении запроса на данные, клиент проверяют метку их последнего изменения: если она не совпадает с меткой в основном хранилище, данные обновляются.
При использовании любого паттерна кэширования важно помнить о когерентности данных, то есть о том, что все клиенты и страницы должны получать одинаково актуальные данные. Для этого часто используется принудительный сброс кэша при изменении данных.
Настройка политики истечения срока действия кэша (TTL)
Срок действия данных в кэше или срок их «жизни» — это время, в течение которого ключ считается актуальным. Стратегия TTL, или time-to-life — утилитарный подход и в чистом виде может привести к некорректности данных в кэше. Ведь очень редко удается заранее просчитать, сколько именно секунд или дней тот или иной ключ останется неизменным и актуальным.
Поэтому большинство систем, в том числе Redis и Memcached при автоматическом освобождении места ориентируются на частоту использования конкретных ключей и время, прошедшее с момента последнего к ним обращения. Хотя кэширование в Redis поддерживает политику volatile-ttl, при которой первыми удаляются ключи с истекшим или коротким оставшимся TTL.
Управление памятью и избегание переполнения кэша
Оперативная память сервера — величина небесконечная, а для хранения кэша выделяется и вовсе лишь ее часть. Значит, каждому разработчику, использующему кэширование, придется столкнуться с проблемой переполнения. Redis и Memcached выполняют удаление устаревших ключей в автоматическом режиме. Например, Redis при достижении лимита памяти перестанет загружать в кэш новые данные и начинает удаление согласно заданным настройкам, но на чтение продолжит работать в прежнем режиме.
Redis поддерживает несколько подходов к очищению кэша: volatile-lru, volatile-ttl, volatile-random, allkeys-lru и allkeys-random, а в Memcached максимальный срок жизни каждого ключа задается в параметрах при его создании. Обе эти системы чаще всего настраиваются для удаления ключей, которые не использовались дольше всего.