Valkey держит данные в памяти и пишет их копию на диск одним из двух способов или обоими сразу. Снимок RDB - это весь набор данных, записываемый через промежутки времени в один компактный файл; append-only файл (AOF) записывает в журнал каждую операцию записи по мере её выполнения и проигрывается при запуске. С включённым AOF и appendfsync everysec - разумной настройкой - сбой стоит не более примерно секунды записей. Только со снимками сбой стоит всего, что произошло после последнего снимка, а по умолчанию это может быть до часа. Если включить оба, вы получите маленькое окно потерь AOF и компактный файл снимка, который можно скопировать в другое место. Ни один из них сам по себе не является backup, потому что оба лежат на том же диске, что и сервер, и ни один не превращает Valkey в базу данных, которая гарантирует, что зафиксированная запись переживёт сбой.
Два механизма на одной картинке#
Клиент получает свой OK, как только запись оказалась в памяти. Всё, что правее, происходит потом, и это ключевой факт о сохранении данных в Valkey: подтверждённая запись ещё не на диске. Сколько она пробудет только в памяти, зависит от настроек ниже.
Снимки RDB#
Снимок - это весь набор данных, сериализованный в один файл, по умолчанию dump.rdb, в каталоге, указанном в dir. Valkey делает снимок автоматически, когда достигнута точка сохранения, и при штатном завершении работы.
save 3600 1 300 100 60 10000dbfilename dump.rdbrdbcompression yesrdbchecksum yesstop-writes-on-bgsave-error yesСтрока save - это пары «секунды и изменения»: снимок через 3600 секунд, если изменился хотя бы один ключ, через 300 секунд, если изменилось хотя бы 100, через 60 секунд, если изменилось хотя бы 10 000. Эти три пары - значение по умолчанию. save "" полностью отключает автоматические снимки.
То, как делается снимок, объясняет и его сильную сторону, и его цену. Valkey вызывает fork(), и дочерний процесс записывает набор данных во временный файл, а по завершении переименовывает его поверх старого. Родительский процесс всё это время продолжает обслуживать клиентов. Форк использует copy-on-write: родитель и потомок разделяют страницы памяти, пока родитель не изменит какую-то из них, и тогда ядро копирует эту страницу. Снимок спокойного набора данных почти не требует дополнительной памяти; набору, в который во время снимка интенсивно пишут, в худшем случае может понадобиться почти вдвое больше его размера, потому что каждая затронутая страница дублируется.
Сильные стороны RDB: один компактный файл, который легко скопировать с машины; быстрая загрузка при запуске, гораздо быстрее проигрывания журнала; и почти никаких затрат между снимками. Слабая сторона: всё записанное после последнего снимка существует только в памяти.
stop-writes-on-bgsave-error yes, значение по умолчанию, стоит понять раньше, чем оно вас удивит. Если фоновое сохранение не удалось - диск заполнен, форк не прошёл, - Valkey отказывается принимать дальнейшие записи с ошибкой MISCONF, исходя из того, что вы скорее предпочтёте узнать об остановке сохранения сейчас, чем обнаружить это после сбоя. Устраните причину, и ошибка уйдёт при следующем успешном сохранении.
Команды: BGSAVE прямо сейчас запускает фоновый снимок; SAVE делает снимок в основном потоке и блокирует всех клиентов до его окончания, поэтому на рабочем сервере её не используйте; LASTSAVE возвращает Unix-время последнего успешного сохранения.
Append-only файл#
AOF записывает каждую команду, изменяющую данные, в том же протоколе, которым пользуются клиенты, и дописывает её в журнал. При запуске сервер проигрывает журнал и возвращается в то же состояние.
appendonly yesappendfilename "appendonly.aof"appenddirname "appendonlydir"appendfsync everysecno-appendfsync-on-rewrite noauto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mbaof-use-rdb-preamble yesaof-load-truncated yesНастройка, которая решает, сколько вы можете потерять, - appendfsync. Запись в файл кладёт данные в кэш операционной системы; только fsync заставляет их оказаться на диске.
appendfsync | Когда данные попадают на диск | Потери в худшем случае | Цена |
|---|---|---|---|
always | После каждой команды записи | Почти ничего | Каждая запись ждёт диск |
everysec | Раз в секунду, в фоновом потоке | Около одной секунды | Небольшая; значение по умолчанию |
no | Когда решит ядро | Десятки секунд | Наименьшая |
everysec - правильный выбор почти для всех. На быстрых NVMe always не так болезнен, как гласит его репутация, но он превращает каждую запись в обращение к диску, и если вам нужна такая гарантия, вам, скорее всего, нужна база данных с настоящими транзакциями. Под большой нагрузкой, если фоновый fsync медленный, everysec может ненадолго расширить окно риска примерно до двух секунд.
Журнал растёт бесконечно, если его не уплотнять. Перезапись строит из текущего набора данных новый минимальный журнал - миллион команд INCR по одному ключу превращаются в один SET - в дочернем процессе после форка, как и снимок. auto-aof-rewrite-percentage 100 запускает перезапись, когда журнал удвоился с прошлого раза, а auto-aof-rewrite-min-size не даёт постоянно перезаписывать крошечные журналы. BGREWRITEAOF запускает перезапись вручную.
Начиная с Redis 7.0, а значит, в любом релизе Valkey, AOF - это не один файл, а каталог appendonlydir, в котором лежат базовый файл, один или несколько инкрементальных файлов и манифест, где они перечислены. С aof-use-rdb-preamble yes (по умолчанию) базовый файл пишется в формате RDB, что сильно ускоряет перезапись и загрузку; инкрементальные файлы хранят команды с того момента. Обращайтесь с каталогом как с единым целым - один файл, скопированный из него, даёт вам фрагмент, а не набор данных.
Оба сразу и что загружается при запуске#
Включайте оба. AOF даёт окно потерь в одну секунду; RDB даёт компактный файл для backup и более быстрый перезапуск, если когда-нибудь понадобится стартовать с него.
При запуске, если appendonly равен yes, Valkey загружает AOF и игнорирует dump.rdb, потому что журнал полнее. Если AOF выключен, загружается снимок. Одно следствие застаёт людей врасплох: если включить appendonly yes в файле конфигурации сервера, у которого данные есть только в dump.rdb, и перезапустить его, он стартует с пустого AOF и поднимается пустым. Чтобы включить AOF на работающем сервере с существующими данными, выполните CONFIG SET appendonly yes на ходу, дождитесь окончания начальной перезаписи (aof_rewrite_in_progress:0 в INFO persistence), а затем приведите в соответствие файл конфигурации.
Противоположный выбор тоже законен. Сервер, на котором нет ничего, кроме кэша, может работать с save "" и appendonly no: ни форков, ни записи на диск, ни ошибок MISCONF, и каждый перезапуск начинается с пустого места. Это разумный размен, когда перестроить кэш дёшево, а база данных за ним выдержит холодный старт. И это неправильный размен в тот момент, когда кто-то кладёт на тот же сервер сессии или очередь задач, - именно так большинство общих экземпляров и оказываются хранителями данных, терять которые никто не собирался. Решайте для каждого сервера отдельно, записывайте решение и по возможности держите данные с разными требованиями к сохранности на разных серверах.
Загрузка занимает время, пропорциональное объёму данных. Пока она идёт, сервер отвечает на команды ошибкой LOADING; клиенты должны повторять запрос, а не считать её фатальной.
Что теряется при каждом виде остановки#
Потери зависят от того, как остановился процесс, а не только от настроек.
| Событие | Только RDB | AOF everysec (с RDB или без) |
|---|---|---|
Штатное завершение (SHUTDOWN, SIGTERM) | Ничего, если настроены точки сохранения | Ничего |
Процесс убит (SIGKILL, нехватка памяти) | Всё после последнего снимка | Примерно последняя секунда |
| Сбой операционной системы или отключение питания | Всё после последнего снимка | Примерно последняя секунда, если диск честно выполняет fsync |
| Диск потерян или повреждён | Всё, если нет копии вне машины | Всё, если нет копии вне машины |
По ошибке выполнен FLUSHALL | Восстановимо из более старой копии снимка | FLUSHALL тоже попадает в журнал - см. ниже |
Последняя строка заслуживает пояснения. FLUSHALL - такая же запись, как и любая другая, поэтому она попадает в AOF. Если заметить её до следующей перезаписи, можно остановить сервер, удалить завершающий FLUSHALL из самого нового инкрементального файла в appendonlydir и снова запустить. После перезаписи данных в журнале уже нет, и поможет только копия, сделанная раньше. Вот почему сохранение данных и backup - разные темы.
Восстановление повреждённого файла#
Файлы обрезаются - сбой посреди записи оставляет в конце AOF половину команды. С aof-load-truncated yes (по умолчанию) Valkey загружает всё до сломанной последней команды, пишет предупреждение в лог и запускается. Если повреждение в середине файла, он отказывается запускаться, и чинить придётся вручную:
$ valkey-check-aof appendonlydir/appendonly.aof.manifest$ valkey-check-aof --fix appendonlydir/appendonly.aof.manifest$ valkey-check-rdb dump.rdbvalkey-check-aof --fix обрезает журнал на первой недопустимой команде, и всё после этой точки теряется - скопируйте каталог, прежде чем запускать его. valkey-check-rdb сообщает, читается ли снимок. Если AOF не подлежит восстановлению, а снимок в порядке, можно стартовать со снимка: отключить AOF, запустить сервер, а затем снова включить AOF на ходу, как описано выше.
Впрочем, большинство восстановлений вообще не связаны с повреждёнными файлами. Это сервер, который запустился, загрузил свой AOF и получил те данные, которые должен был. Это обычный случай, и ради него всё и затевается.
Как следить за сохранением#
Сохранение ломается тихо, пока перезапуск это не обнаружит, так что проверяйте его так же, как всё остальное. В INFO persistence есть всё:
$ valkey-cli -h db.example.net -p 6380 --askpass INFO persistenceloading:0rdb_changes_since_last_save:184rdb_bgsave_in_progress:0rdb_last_save_time:1791449103rdb_last_bgsave_status:okaof_enabled:1aof_rewrite_in_progress:0aof_last_bgrewrite_status:okaof_last_write_status:okПоля, на которые стоит настроить оповещения: rdb_last_bgsave_status и aof_last_bgrewrite_status должны быть ok; aof_last_write_status должен быть ok; rdb_last_save_time должен быть недавним, если данные меняются. Если rdb_changes_since_last_save растёт без сохранений, снимки остановились. В логе сервера строка о том, что форк не удался или что фоновое сохранение завершилось с ошибкой, - раннее предупреждение о том, что запас памяти кончился.
Сохранение данных - это не backup#
Оба файла лежат на том же диске, что и сервер. Удалённый сервер, вышедший из строя диск, ошибочный FLUSHALL, который уже переписан в AOF, или ошибка в приложении, затёршая половину ключей, - во всех этих случаях у вас остаются надёжно сохранённые копии неправильного состояния. Backup - это копия где-то в другом месте, сделанная до того, как возникла проблема.
Для Valkey это просто, потому что снимок - один файл:
- Запустите свежий снимок командой
BGSAVEи дождитесь, пока изменитсяLASTSAVE. - Скопируйте
dump.rdbс машины - на другой сервер, в объектное хранилище, куда угодно, что не разделяет тот же сбой. - Храните несколько поколений, чтобы проблема, замеченная с опозданием в неделю, всё ещё была исправима.
Если сервер это позволяет, valkey-cli --rdb backup.rdb получает снимок по сети, вообще не трогая диск сервера, и это удобно делать с хоста для backup. И время от времени восстанавливайте снимок в черновой экземпляр - почему именно этот шаг важнее всего, объясняет статья проверка восстановления до того, как оно понадобится. Общее расписание описано в статье backup и восстановление баз данных.
А затем решите, нужен ли этим данным backup вообще. Кэшу - нет: его можно перестроить из базы данных. Сессиям обычно тоже нет: их потеря лишь разлогинит людей. Очередям ожидающих задач, счётчикам, по которым вы выставляете счета, и всему, у чего нет другой копии, - нужен.
Сохранение данных на сервере Valkey в RE:NODE#
Серверы Valkey в линейке баз данных сохраняют данные на диск и через AOF, и снимками, так что перезапуск - нажали ли вы кнопку или сервер был остановлен на пределе памяти и чисто перезапущен, а именно так платформа обрабатывает нехватку памяти, - проигрывает журнал и возвращает данные, которые были, за вычетом разве что последнего мгновения записей. Такое поведение на пределе памяти - ещё и практическая причина держать набор данных в пределах доступного объёма, указанного для каждого тарифа, а не заявленного числа: дочерним процессам снимка и перезаписи нужно место. Слоты для backup входят в каждый тариф Valkey начиная с 512 МБ; у тарифа на 256 МБ их нет, поэтому на нём, если данные важны, делайте собственные копии вне машины, как описано выше. Backup в панели восстанавливаются одной кнопкой.
FAQ#
Что использовать - AOF или RDB?
Оба, если данные хоть сколько-нибудь важны. AOF с appendfsync everysec ограничивает потери при сбое примерно секундой записей; RDB даёт компактный файл, который можно скопировать с машины, и более быстрый перезапуск. Если на сервере только кэш, разумно ограничиться снимками или вовсе обойтись без сохранения.
Теряет ли Valkey данные при перезапуске?
При штатном перезапуске с включённым сохранением - нет: он сохраняет данные при завершении и загружает их при запуске. Принудительная остановка теряет всё, что не успело попасть на диск, - около секунды с AOF everysec или всё после последнего снимка без AOF.
Почему сервер отказывается принимать записи с ошибкой MISCONF?
Фоновое сохранение не удалось, а stop-writes-on-bgsave-error включён, поэтому сервер перестаёт принимать записи, пока сохранение снова не заработает. Причина почти всегда в заполненном диске или в форке, которому не хватило памяти. Какая именно, скажет лог сервера.
Стоит ли appendfsync always своей цены?
Редко. Он заставляет каждую запись ждать подтверждения от диска, что резко снижает пропускную способность, а защищает он последнюю секунду перед сбоем. Если потеря этой секунды недопустима, данным, скорее всего, место в транзакционной базе данных вроде PostgreSQL, а Valkey должен стоять перед ней.
Насколько большим станет AOF?
После каждой перезаписи - примерно пропорциональным набору данных, а между перезаписями он растёт с каждой записью. С настройками по умолчанию он перезаписывается, когда удваивается, так что рассчитывайте, что он будет от одного до двух размеров данных плюс файл снимка рядом. Оставьте место на диске для обоих и для временной копии при перезаписи.




Комментарии
Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.