← Назад к вопросам

Как сделать persistence Redis?

1.7 Middle🔥 121 комментариев
#DevOps и инфраструктура#Базы данных (NoSQL)

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как сделать 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.

Как сделать persistence Redis? | PrepBro