Как сделать persistence Redis?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как сделать persistence Redis
Persistence в Redis — это механизм сохранения данных на диск, чтобы они не потерялись при перезагрузке сервера. Redis предоставляет два основных подхода: RDB (снимки) и AOF (лог операций).
1. RDB (Redis Database) — Snapshot-based persistence
RDB сохраняет полный снимок данных в памяти на диск в определённый момент времени.
Конфигурация в redis.conf:
# Сохранить, если было N изменений за M секунд
# save <seconds> <changes>
save 900 1 # Сохранить если 1 изменение за 15 минут
save 300 10 # Сохранить если 10 изменений за 5 минут
save 60 10000 # Сохранить если 10000 изменений за 1 минуту
# Отключить автоматические сохранения
# save ""
# Файл снимка
dbfilename dump.rdb
dir ./
Ручное сохранение из Python:
import redis
r = redis.Redis(host="localhost", port=6379, db=0)
# SAVE — синхронное сохранение (блокирует Redis)
r.save()
# BGSAVE — фоновое сохранение (асинхронно)
r.bgsave()
# Проверить последний успешный снимок
info = r.info("persistence")
print(f"Последний снимок: {info["last_save_time"]}")
print(f"Статус: {info["rdb_last_bgsave_status"]}")
Плюсы RDB:
- Быстрое восстановление при запуске
- Небольшой размер файла (сжатие)
- Хорош для резервных копий
Минусы RDB:
- Потеря данных между снимками
- SAVE блокирует сервер
- BGSAVE требует fork процесса (дорого на больших памятях)
2. AOF (Append-Only File) — Command logging
AOF записывает каждую команду изменения в лог на диск. При перезагрузке Redis переигрывает все команды.
Конфигурация в redis.conf:
# Включить AOF
appendonly yes
# Имя файла AOF
appendfilename "appendonly.aof"
# Как часто синхронизировать с диском
# always — после каждой команды (медленно, но безопасно)
# everysec — раз в секунду (компромисс)
# no — оставить операционной системе (быстро, но небезопасно)
appendfsync everysec
# Процент переписи AOF
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
Работа с AOF из Python:
import redis
r = redis.Redis(host="localhost", port=6379, db=0)
# Переписать AOF файл (удалить дублирующиеся команды)
r.bgrewriteaof()
# Проверить статус AOF
info = r.info("persistence")
print(f"AOF включён: {info["aof_enabled"]}")
print(f"AOF текущая переписьь: {info["aof_rewrite_in_progress"]}")
print(f"Размер AOF: {info["aof_current_size"]}")
Плюсы AOF:
- Минимальная потеря данных (каждую секунду)
- Лог команд может быть полезен для отладки
- Автоматическое сжатие через rewrite
Минусы AOF:
- Медленнее RDB при восстановлении
- Больший размер файла
- Риск повреждения файла
3. Комбинированный подход (RDB + AOF)
Вы можете использовать обе стратегии одновременно:
# redis.conf
save 900 1 # RDB каждые 15 минут
appendonly yes # AOF всегда включен
appendfsync everysec # AOF каждую секунду
При перезагрузке Redis сначала загружает RDB (быстро), потом переигрывает команды из AOF после RDB (минимальная потеря данных).
4. Практический пример: надёжное хранилище
import redis
import time
from typing import Any
class PersistentRedisStore:
def __init__(self, host="localhost", port=6379):
self.r = redis.Redis(host=host, port=port, db=0)
def set_with_persistence(self, key: str, value: Any,
wait_save: bool = False) -> None:
"""Сохраняет значение и гарантирует persistence"""
# Сохраняем в Redis
self.r.set(key, value)
# Опционально ждём синхронизации с диском
if wait_save:
self.r.bgsave()
# Ждём завершения в фоне (не блокирует)
time.sleep(0.1) # Даём время на инициализацию
def ensure_persistence(self) -> None:
"""Гарантирует, что все данные на диске"""
# RDB снимок
self.r.bgsave()
# AOF переписать для сжатия
self.r.bgrewriteaof()
def get_persistence_stats(self) -> dict:
"""Получает статистику persistence"""
info = self.r.info("persistence")
return {
"aof_enabled": info.get("aof_enabled"),
"aof_size": info.get("aof_current_size"),
"aof_rewrite_in_progress": info.get("aof_rewrite_in_progress"),
"rdb_last_save": info.get("rdb_last_save_time"),
"rdb_status": info.get("rdb_last_bgsave_status"),
}
# Использование
store = PersistentRedisStore()
store.set_with_persistence("important_key", "important_value")
print(store.get_persistence_stats())
5. Восстановление данных
# При запуске Redis:
redis-server /path/to/redis.conf
# Redis автоматически:
# 1. Загружает dump.rdb (если существует)
# 2. Переигрывает appendonly.aof (если включен AOF)
Восстановление из бэкапа:
# Копируем файлы
cp dump.rdb.backup dump.rdb
cp appendonly.aof.backup appendonly.aof
# Перезапускаем Redis
redis-server
6. Мониторинг persistence
import redis
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class RedisMonitor:
def __init__(self, redis_client):
self.r = redis_client
def check_persistence_health(self) -> bool:
"""Проверяет здоровье persistence"""
info = self.r.info("persistence")
# Проверяем RDB
if info["rdb_last_bgsave_status"] != "ok":
logger.error("Ошибка RDB сохранения")
return False
# Проверяем AOF
if info["aof_enabled"] and info["aof_last_rewrite_time"] == 0:
logger.warning("AOF никогда не переписывался")
# Проверяем время последнего снимка
last_save = info["rdb_last_save_time"]
current_time = int(time.time())
time_since_save = current_time - last_save
if time_since_save > 3600: # Более часа
logger.warning(f"Нет RDB снимков {time_since_save}s")
return True
# Использование
monitor = RedisMonitor(r)
monitor.check_persistence_health()
7. Лучшие практики
1. Выбор стратегии:
- Только RDB: для кэшей, где потеря данных приемлема
- Только AOF: для критичных данных, где нужна надёжность
- RDB + AOF: для максимальной надёжности
2. Размер памяти:
# Ограничить использование памяти
maxmemory 2gb
maxmemory-policy allkeys-lru # Удаляй старые ключи при полноте
3. Автоматические тесты восстановления:
def test_recovery():
# 1. Добавляем данные
r.set("test_key", "test_value")
# 2. Сохраняем
r.bgsave()
# 3. "Перезагружаем" (очищаем и восстанавливаем)
r.flushdb() # Очистить память
# В реальности перезапускаем Redis процесс
# 4. Проверяем восстановление
assert r.get("test_key") == b"test_value"
4. Мониторинг в production:
- Отслеживай размер RDB файла
- Мониторь время переписи AOF
- Настрой алерты на ошибки при сохранении
- Регулярно тестируй восстановление из бэкапов
Правильная конфигурация persistence критична для надёжности Redis в production.