Программа курса

Модуль 04 / Урок 17 из 27

AOF: журнал каждой записи

Теория и практика

AOF (Append Only File) дописывает каждую изменяющую команду в лог; при старте Redis переигрывает журнал и восстанавливает состояние. Это механизм для «потеряем не больше секунды».

Настройка и fsync-политики

appendonly yes
appendfilename "appendonly.aof"

appendfsync always     # fsync после КАЖДОЙ команды: максимум сохранности, минимум скорости
appendfsync everysec   # fsync раз в секунду фоновым потоком — РЕКОМЕНДУЕМЫЙ компромисс
appendfsync no         # решает ОС (обычно ~30с буферов): быстро, но непредсказуемо
ПолитикаRPO (потеря при аварии)Цена
always~0 (команда подтверждена после записи на диск)латентность записи = диск; X10–100 на HDD
everysec≤ 1 секпочти незаметна
noдо десятков секунд, недетерминированоминимальна

При everysec, если fsync задержался (медленный диск), Redis по умолчанию останавливает запись (no-appendfsync-on-rewrite no) вместо бесконечного накопления — следите за aof_delayed_fsync в INFO persistence.

Rewrite: журнал не должен расти вечно

AOF содержит каждую команду — включая сотни инкрементов одного счётчика. Rewrite переписывает журнал в «минимальное» представление текущего состояния (SET вместо тысяч команд).

  • Механика как у BGSAVE: fork + ребёнок пишет новый файл; родитель копит новые команды в буфер и дописывает в конец готового файла;
  • Триггеры: auto-aof-rewrite-percentage 100 (журнал вырос на 100% от последнего rewrite) и auto-aof-rewrite-min-size 64mb;
  • Ручной: BGREWRITEAOF;
  • Замечание для отчётности: SET снимает TTL, но в AOF само истечение пишется как DEL/UNLINK при активной вычистке — восстановленный датасет совпадает с моментом снимка.

Multi-part AOF (Redis 7+)

С 7-й версии AOF — это «базовый» файл (результат последнего rewrite) + инкрементальные файлы + манифест. Плюсы: быстрый рестарт (база загружается без переигрывания всей истории), устойчивость к частичной порче, возможность отключить rewrite во время работы.

Целостность и починка

# Проверка целостности файла
redis-check-aof appendonly.aof
# Усечение оборванного хвоста (частый случай после аварии диска)
redis-check-aof --fix appendonly.aof
⚠️ Рестарт с AOF переигрывает журнал: восстановление большого датасета заметно медленнее, чем загрузка RDB. Это ещё одна причина держать обе технологии: RDB для скорости рестарта, AOF для минимума потерь (Redis грузит AOF, если он есть — он новее).

RDB vs AOF — итог

СценарийРекомендация
Чистый кешRDB (или ничего)
Смешанное, потеря ≤1с терпимаRDB + AOF everysec (стандарт индустрии)
Хранилище, потеря ≤1с недопустимаAOF always + реплики + бэкапы; честно считайте цену латентности

Практика

  1. Включите AOF everysec, запишите 1000 ключей, kill -9 процесса сразу после последней записи, поднимите: посчитайте фактическую потерю.
  2. Повторите то же с appendfsync always и сравните потери и throughput (redis-benchmark -t set -P 1).
  3. Сделайте BGREWRITEAOF на журнале с миллионом INCR одного счётчика — сравните размер файла до/после.
  4. Найдите в INFO persistence: aof_enabled, aof_last_bgrewrite_status, aof_current_size, aof_delayed_fsync.
Мини-квиз

1. Сколько данных потеряете на everysec при отключении питания? — До ~1 секунды подтверждённых записей.

2. Зачем rewrite, если команды и так применяются? — Компактность и скорость восстановления: журнал содержит историю, а не состояние.

3. Почему Redis при старте предпочитает AOF? — Он обычно более полный (новее), чем последний RDB-снимок.