Настраиваем бэкап сервера баз данных Redis

08/11/2016

Как известно сервер баз данных Redis хранит все данные в оперативной памяти, что может привести к их потере, если сервер будет внезапно остановлен, или компьютер потеряет питание. Для разрешения этой пролемы Redis, как известно, можно настроить на периодическое копирование содержимого оперативной памяти на диск, чтобы при следующем старте просто загрузить указанный файл обратно в память и продолжить работу. Однако даже такой подход не решает проблему, что называется disaster recovery - восстановления после сбоя всего и вся, с нуля, возможно даже на другой машине. Для этого резервная копия базы данных Redis должна храниться в месте, отличном о том, где на данный момент работает сервер Redis. Вы скажите, что нужно просто скопировать последний созданный Redis слепок данных на другую машину или в облако, и backup готов. Однако, теоритически может так оказаться, что вы будете копировать файл, который обычно называется dump.rdb, имеено в тот момент, когда Redis решит делать очередной flush (копирование данных из памяти на диск), что может привести к невозможности восстановления в случае краха сервера.

Хорошим, казалось бы, вариантом создания бэкапа Redis будет, используя программу redis-cli, получить список всех ключей сервера с помощью команды KEYS \*, сделать DUMP их значений, записать в файл, а потом попытаться восстановить их с помощью команды RESTORE. И это действительно работает, но вот восстановить такой файл не представляется возможным, потому что он будет содержать разного рода символы, которые если и не заставят ваш интерпретатор зависнуть, то уж точно не позволят ему корректно обработать значение ключа. Скорее всего вы получите сообщение вида

(error) ERR DUMP payload version or checksum are wrong

К счастью, redis-cli позволяет подключиться в серверу Redis под видом slave - подчиненного сервера, и запросить копию актуального файла dump.rdb, который уже можно безбоязненно сохранить в любое место на вашей файловой системе. В этом случае вы получаете абсолютно консистентный бэкап Redis, не вмешиваясь в протоколы работы сервера, а используете штатный механизм master-slave. Сделать это можно следующим способом из коммандной строки:

redis-cli --rdb backup.rdb

Данная команда заставит redis-cli попытаться подключиться в серверу на этой же машине по адресу 127.0.0.1 к порту 6379, запросить копию актуального dump.rdb и сохранить её в файл backup.rdb в текущем каталоге. Если вы хотите подключиться к серверу не локально, а по сети, то возможно следующие дополнительный ключи к redis-cli будут для вас полезны:

-h задает IP-адрес сервера
-p задает TCP-порт сервера, если он отличен от 6379
-a задает пароль, если сервер требует таковой

Конечно же мы не хотим всё время помнить о том, что нам нужно сделать бэкап Redis, а хотим, чтобы он проходил автоматически. Для этого создадим простой bash-скрипт:

#!/bin/bash
HOST='SERVER_IP'
PORT='SERVER_PORT'
PASSWORD='SERVER_PASSWORD_IF_NEED'
DATE=`date +%Y%m%d`
DAYSTOSTORE='WHERE_TO_PUT_BACKUPS'
STORAGE='HOW_MANY_DAYS_KEEP_IT'  
 
rm -f `find ${STORAGE} -type f -mtime +${DAYSTOSTORE}`  
 < br /> if [ -f ${STORAGE}/${DATE}_dump.rdb ]; then
 echo "File exists.\
 That can mean, that backup is already done"
 exit 0
else
  if [ -z ${PASSWORD} ]; then
    REDIS_CLI_COMMAND_LINE='-h '$HOST' -p '$PORT' --rdb '${STORAGE}'/'${DATE}'_dump.rdb'
  else
    REDIS_CLI_COMMAND_LINE='-h '$HOST' -p '$PORT' -a '${PASSWORD}' --rdb '${STORAGE}'/'${DATE}'_dump.rdb'
  fi
  redis-cli $REDIS_CLI_COMMAND_LINE
  if [ $? -eq 0 ]; then
    echo "Backup succsess"
  else
    echo "Backup error"
  fi
fi

Просто измените 7 переменных в начале скрипта на нужные вам значения, если сервер требует пароль впишите его, если нет, то просто оставьте пустые кавычки (''), переменную DATE можно не трогать - она допишет в начало названия файла с бэкапом текущую дату.  Не забудьте дать ему права на исполнение:

chmod +x NAME_OF_SCRIPT

Испытатйе его - вы должны получить файл с названием, состоящим из текущей даты + "_dump.rdb". Теперь попробуйте на тестовом инстансе Redis загрузить бэкап в качестве основной базы. Получилось? Отлично! Можно смело интегрировать наш скрипт с полюбившимся вам scheduler'ом, которыми являются, например, CRON или Systemd Timer. Если же нет, пишите в комментариях, мы рассмотрим ваш случай более детально.

Темы: