Redis - это NoSQL база данных, которая хранит данные в виде ключ-значение. Кроме удобного и понятного формата хранения есть еще одно преимущество - это быстрая база данных поддержка которой реализована на множестве языков. В этой статье рассмотрим как установить такую базу на Ubuntu создавать и восстанавливать бэкапы.
Для чего нужен Redis
В любом языке программирования существуют массивы имеющие следующий вид:
{'key': {'key2': 'value', 'key3': ['value', 'value3']}}
Подобный вид данных сложно сохранить в SQL базы. Что бы это сделать нам нужно будет создать несколько таблиц (по принципу нормализации), а затем выстраивать связь. Можно так же сохранить эти данные как JSON, но это не лучший способ для работы с SQL.
Структура данных, которую мы храним Redis, очень похожа на тот тип, что представлен выше. Т.е. разработчик интуитивно понимает как работать с базой так как она похожа на уже знакомый тип данных.
Кроме этого, Redis может хранить данные ограниченное количество времени, а затем автоматически удалять. Для примера - пользователи часто запрашивают историю покупок. Так как это операция может быть трудоемкой для SQL - ее можно выполнить 1 раз, а результат сохранить как временный в Redis. Пользователь, повторно просматривая историю, будет запрашивать данные из Redis, а не из SQL. Этот процесс может быть и обратным, т.е. сначала данные заносятся в Redis, а потом в SQL.
В основном данные хранятся в памяти сервера, но могут быть выгружены на диск. Если это какие-то важные данные, например сессии пользователей, то можно настроить репликацию и создать кластер.
Схема, которая показывает одну из реализаций при работе с пользователями:
Установка из репозитория
Перед установкой Redis нужно обновить список доступных пакетов в репозитории Ubuntu:
sudo apt update
Сам пакет находится в стандартном репозитории Ubuntu, и мы можем его установить оттуда. Отмечу, что чаще всего это не самая последняя версия:
sudo apt install redis-server
Перед запуском сервиса нам нужно изменить значение параметра 'supervised'. Этот параметр указывает на систему обслуживания сервисов. В современных версиях Ubuntu, а так же CentOS, все сервисы обслуживаются 'systemd'. Мы должны открыть следующий файл:
sudo vim /etc/redis/redis.conf
И изменить следующее значение:
# было supervised no
supervised systemd
В этом же файле вы можете изменить место хранения данных. Значение по умолчанию '/var/lib/redis':
Далее включим сервер:
sudo systemctl enable --now redis-server
Проверка работы сервиса
Проверим, что запуск сервиса был успешен:
sudo systemctl status redis-server
Мы так же можем проверить работу сервера через внутренние команды. Для этого нужно использовать redis-cli:
redis-cli
ping
Для выхода из консоли redis выполните:
exit
Установка последней версии с компиляцией
На момент написания статьи, в репозитории Ubuntu, доступна 5-ая версия Redis, а на официальном сайте проекта пишется о вышедшей 6+ версии. Мы можем скачать последнюю версию с сайта проекта, затем скомпилировать и установить ее.
Минус такого подхода в том, что программы типа apt не будут знать об этой установке и зависимых программах. С другой стороны, как указано на официальном сайте, единственные зависимости - это компилятор gcc и libc.
Что бы установить последнюю версию, первое что нужно сделать, это скачать и распаковать архив. По ссылке ниже всегда находится последняя версия программы:
wget https://download.redis.io/redis-stable.tar.gz
Скорее всего вам понадобится ряд пакетов, которые могут выполнять компиляцию программы (они могут быть уже установлены):
sudo apt install build-essential tcl pkg-config
Далее распакуем архив и скомпилируем ПО из его исходников:
tar xzf redis-stable.tar.gz
cd redis-stable
make MALLOC=libc
После компиляции, опционально, можно запустить проверку, которая будет длиться в 3-4 раза дольше предыдущего шага:
make test
Выполним установку Redis из компилированных исходников:
sudo make install
Создадим директорию в которой будем хранить файл конфигурации. Файл конфигурации с настройками по умолчанию находится в текущей папке - его мы должны скопировать:
sudo mkdir /etc/redis
sudo cp redis.conf /etc/redis
В файле конфигурации, в параметре 'supervised' мы так же должны указать систему инициализации. В ubutu это systemd:
sudo vim /etc/redis/redis.conf
Не закрывая этот файл так же нужно указать директорию, в которой будет храниться база Redis. Этой директорией, обычно, является '/var/lib/redis/', а устанавливается она в параметре 'dir':
Создание пользователя и выдача прав
Доступ к папке, в которой будет храниться база, должны иметь только пользователи root и redis. Системного пользователя redis нам нужно создать самостоятельно. Это можно сделать через следующие команды:
sudo adduser --system --group --no-create-home redis
Теперь создадим папку, в которой будет храниться база. Выдадим нужные права и сменим владельца:
sudo mkdir /var/lib/redis
sudo chown redis:redis /var/lib/redis
sudo chmod 770 /var/lib/redis
Создание сервиса
Последним этапом будет создание файла-сервиса, который сможет читать 'systemd'. Этот файл мы должны создать по следующему пути:
sudo vim /etc/systemd/system/redis.service
В этот файл поместим следующее содержимое:
[Unit]
Description=Redis In-Memory Data Store
After=network.target
[Service]
User=redis
Group=redis
ExecStart=/usr/local/bin/redis-server /etc/redis/redis.conf
ExecStop=/usr/local/bin/redis-cli shutdown
Restart=always
[Install]
WantedBy=multi-user.target
Запустим сервис и проверим его работу:
sudo systemctl enable --now redis.service
sudo systemctl restart redis.service
sudo systemctl status redis.service
Запустим cli и выполним некоторые проверки там:
redis-cli
ping
set test1 test2
Если ваш вывод аналогичен данным со скриншота, то установка прошла успешно.
Настройка удаленного подключения
Для настройки удаленного подключения нужно изменить 2 параметра. Эти параметры связаны с интерфейсом на который может прийти подобный запрос и паролем.
IP адрес интерфейса, с которого может прийти запрос, устанавливается в параметре 'bind'. По умолчанию в этом параметре установлено значение '127.0.0.1', что дает возможность подключаться только локально.
К существующему параметру мы должны добавить IP адрес интерфейса, который будет принимать подключения к Redis. Узнать адрес интерфейса мы можем следующим способом:
ip a
Есть альтернативный подход в виде адреса '0.0.0.0', который говорит о возможности подключения с любого интерфейса. Попробуйте его, если столкнетесь с ошибками.
Изменить параметр 'bind' мы можем открыв конфигурационный файл:
sudo vim /etc/redis/redis.conf
Перезапустите сервис:
sudo systemctl restart redis-server
Если у вас выключен файервол - вы сможете подключиться к Redis. Иначе вам нужно прописать правила, которые разрешают подключение к 6379 TCP порту.
Прописать правило, которое разрешить подключение только диапазону адресов в следующей подсети '192.168.0.0/16', можно так:
sudo ufw allow from 192.168.0.0/16 to any port 6379 proto tcp
Альтернативно вы можете разрешить подключение всем используя следующую команду:
sudo ufw allow 6379
Аутентификация и создание пароля
На данный момент любой пользователь может подключиться к Redis, если IP адреса совпадают. Мы можем установить пароль, который будет запрашиваться перед подключением. Для этого вам нужно найти и раскомментировать следующую строчку в файле конфигурации:
# requirepass foobared
Вместо 'foobared' вы должны ввести свой пароль. Как написано в самом файле конфигурации - Redis это быстрая база и может принимать 150к попыток ввода пароля в секунду. В связи с этим простой перебор паролей (брутфорс) весьма вероятная проблема. Разработчики советуют использовать более длинные пароли, чем вы это делаете обычно.
Вы можете сгенерировать длинный и безопасный пароль используя 'openssl':
openssl rand 60 | openssl base64 -A
Пример установленного пароля:
sudo vim /etc/redis/redis.conf
Повторно перезагружаем сервис что бы изменения вступили в силу:
sudo systemctl restart redis-server
Теперь вы можете подключаться удаленно используя пароль.
Удаленные подключения, чаще всего, выполняются какой-то библиотекой, в которой реализован процесс аутентификации. Если вы планируете подключаться локально, то этот процесс может потребовать ручного ввода данных. Что бы пройти аутентификацию локально мы должны войти в CLI, а затем использовать команду 'auth' с вашим паролем:
redis-cli
auth ваш_пароль
Как видно на примере выше мы получим ошибку '(error) NOAUTH Authentication required.' если не введем пароль.
Бэкап и восстановление
В Redis существует 3 модели работы с бэкапом:
- RDB - создание бэкапов с определенными интервалами. Состоит из 1-ого файла;
- AOF (append only file) - создание бэкапа после каждой записи данных (журналирование команд). Состоит из 2 файлов;
- RDB+AOF - совмещает обе предыдущих модели, но по умолчанию будет восстанавливаться AOF т.к. имеет более актуальную информацию.
Создание бэкапов так же можно отключить. По умолчанию включен RDB, а AOF отключен.
Большая часть изменений связанных с бэкапом делается в конфигурационном файле:
sudo vim /etc/redis/redis.conf
Настройка RDB
Открыв конфигурационный файл можно увидеть, параметры 'save', которые имеют следующее значения:
save <количество секунд> <количество изменений>
Т.е. выгрузка в файл происходит через определенный интервал и при условии какого-то количества изменений в базе. Если убрать эти строки, то вы отключите RDB.
Создать бэкап можно так же через CLI выполнив одну из двух команд:
- SAVE - блокирует работу базы до создания бэкапа.
- BGSAVE - клонирует (fork()) существующий процесс Redis и выгружает его данные на диск. После этого процесс завершает работу. Таким образом нет блокировок, но возрастает требование к памяти.
Настройки установленные в конфигурационном файле всегда выполняют BGSAVE. Просто SAVE выполняется только через CLI.
Пример выполнения бэкапа через консоль:
redis-cli SAVE
Путь сохранения файла бэкапа и само его название определяется в конфигурационном файле. По умолчанию оно равно: '/var/lib/redis/dump.rdb'.
Что бы восстановить подобный файл, мы должны выполнить следующее:
- Остановить сервер Redis. Иначе файл будет перезаписан;
- Скопировать файл с бэкапом в директорию где был создан бэкап. Названия меняться не должно. Т.е. если бэкап был взят по пути '/var/lib/redis/dump.rdb', то и восстанавливаться он будет отсюда;
- Запустить Redis.
Порядок команд для восстановления:
sudo systemctl stop redis-server
sudo cp ./backup.rdb /var/lib/redis/dump.rdb
sudo systemctl start redis-server
Настройка AOF
Работу с базой можно настроить через принцип логов (типа транзакционных логов в SQL базах). Каждая команда записи и изменения записывается в файл с расширением '.aof'. Из-за того что файл '.aof' хранит все выполненные команды (которые могут повторяться 100-ни раз), он может весомо превышать основной файл данных.
Когда файл '.aof' достигает критической отметки, установленной в настройках, он повторно выгружает все данные из памяти в новый файл. Так как выгрузка идет из памяти, а не из файла '.aof', у нас уже нет дубликатов. Если к серверу поступает какая-то новая команда она записывается в старый и новый файл. После полной выгрузки старый файл заменяется новым.
Изменить принцип работы бэкапа можно в конфигурационном файле. Кроме параметров журналирования есть и другие:
- appendonly no - говорит, нужно ли выполнять AOF бэкап. По умолчанию отключен. Нужно установить 'yes' что бы включить;
- appendfilename "appendonly.aof" - имя файла, которое будет создаваться при бэкапе и читаться при восстановлении;
- appendfsync everysec - как часто нужно выполнять выгрузку. По умолчанию - каждую секунду. Можно так же установить параметр 'always' (сразу после изменения данных) и 'no' (раз в 30 секунд);
- auto-aof-rewrite-min-size 64mb - минимальный размер AOF файла, после которого произойдет перезапись;
- auto-aof-rewrite-percentage 100 - на сколько процентов должен увеличится размер файла после последней перезаписи. Если первая запись сработала при 64mb, то при значении 100%, она повторно сработает на 128mb. Значение 0 - отключение автоматической перезаписи.
Перед включением AOF важно помнить, что если вы его только включили, то все данные будут стерты. После установки параметров и перезапуске сервера, Redis попробует прочитать файл с расширением '.aof'. Так как его нет - будет создан новый, пустой, файл. Избежать это можно установкой параметра через CLI:
sudo redis-cli
CONFIG SET appendonly yes
CONFIG REWRITE
Если у вас появится ошибка '(error) ERR Rewriting config file: Permission denied', то попробуйте сменить владельца папки:
sudo chown redis:redis /etc/redis/redis.conf
Что бы не ждать ситуации, когда файл журнала будет перезаписан, можно выполнить следующую команду:
BGREWRITEAOF
Пример на скриншоте ниже показывает, что файл состоял из 33 строк. После выполнения команды 'BGREWRITEAOF' размер файла сократился до 1 строки т.к. содержал в себе дублирующие команды:
Бэкап будет находиться по следующему пути: '/var/lib/redis/appendonly.aof' (папка и название файла по умолчанию).
Что бы выполнить восстановление базы - вы так же должны остановить сервис Redis:
sudo systemctl stop redis-server
Как уже писалось раньше, при включенном AOF и RDB, всегда будет искаться и восстанавливаться файл '.aof'. Из-за такого поведения, если вам нужно восстановить базу '.rdb', изначально вам нужно отключить AOF. Если вы и планировали восстанавливаться AOF, то вам просто нужно переместить файл по пути '/var/lib/redis/appendonly.aof', и включить сервер:
sudo cp ./appendonly.aof /var/lib/redis/
sudo systemctl start redis-server
Какую модель бэкапа использовать
Выбор модели, которую стоит использовать, зависит от ресурсов выделенных под Redis и важности данных.
Если диски у вас и так сильно нагружены, а потеря данных за последние 5-10 минут не является критической, то RDB лучший вариант. Так же стоит учитывать, что при бэкапе выполняется fork()(клонирование) основного процесса, что повышает требование к оперативной памяти.
Если диски у вас не самое слабое место и вам нужно максимально сохранить данные - лучший вариант AOF. Работу этой модели вы можете настроить с сохранением после каждой команды.
...