← Назад к вопросам
Что такое снимок (snapshot) в Redis?
2.0 Middle🔥 171 комментариев
#DevOps и инфраструктура#Django
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Снимок (Snapshot) в Redis
Snapshot (RDB — Redis Database) — это механизм сохранения полного состояния базы данных Redis на диск в определённый момент времени. Это бинарный файл, который содержит весь набор ключей и значений.
Основная концепция
Redis хранит данные в оперативной памяти, что делает его очень быстрым, но уязвимым к потере данных при отключении. Snapshot позволяет периодически сохранять состояние БД на диск:
# Пример работы с Redis и снимками
from redis import Redis
redis_client = Redis(host="localhost", port=6379)
# Установка значений
redis_client.set("user:1:name", "Alice")
redis_client.set("user:1:email", "alice@example.com")
redis_client.set("counter", 100)
# Создание снимка (выполняется на сервере)
redis_client.bgsave() # Background Save
print("Снимок создан")
# Все данные сохранены на диск в файл dump.rdb
Типы снимков
1. SAVE — синхронное сохранение
redis_client.save() # Блокирует сервер до завершения
# Во время SAVE:
# - Все клиенты ждут
# - Запросы не обрабатываются
# - Данные записываются на диск
2. BGSAVE — асинхронное сохранение
redis_client.bgsave() # Background Save
# Во время BGSAVE:
# - Создаётся дочерний процесс (fork)
# - Основной процесс продолжает обрабатывать запросы
# - Дочерний процесс пишет на диск
# - Клиенты не блокируются
Конфигурация снимков
# В файле redis.conf:
"""
# Сохранять снимок при условиях:
# save <seconds> <changes>
# - Каждые 15 минут, если было 1 или больше изменений
save 900 1
# Каждые 5 минут, если было 10 или больше изменений
save 300 10
# Каждую минуту, если было 10000 или больше изменений
save 60 10000
# Отключить автосохранение
save ""
# Файл для снимков
dbfilename dump.rdb
# Директория для сохранения
dir ./
"""
Файловая структура снимка
# RDB файл содержит:
"""
dump.rdb:
├── Версия RDB
├── Метаинформация (версия Redis, время создания)
├── Выбранная БД (обычно DB 0)
├── Все ключи и значения
│ ├── Тип данных
│ ├── Ключ
│ ├── Значение
│ ├── TTL (время жизни)
├── Контрольная сумма (CRC64)
└── EOF маркер
"""
Процесс создания снимка
import time
from redis import Redis
redis = Redis()
# Шаг 1: Установка данных
for i in range(1000):
redis.set(f"key:{i}", f"value_{i}")
redis.expire(f"key:{i}", 3600) # 1 час
print(f"Размер БД: {redis.dbsize()} ключей")
# Шаг 2: Запуск BGSAVE
start_time = time.time()
redis.bgsave()
print("BGSAVE запущен")
# Шаг 3: Проверка статуса
while True:
info = redis.info('persistence')
if info['rdb_bgsave_in_progress']:
elapsed = time.time() - start_time
print(f"Сохранение в прогрессе... ({elapsed:.1f}s)")
time.sleep(1)
else:
print(f"Сохранение завершено за {time.time() - start_time:.1f}s")
break
# Шаг 4: Проверка файла
last_save = info['rdb_last_save_time']
changes_since = info['rdb_changes_since_last_save']
print(f"Последний снимок: {last_save}")
print(f"Изменений с последнего снимка: {changes_since}")
Восстановление данных из снимка
# Redis автоматически восстанавливает данные при запуске
# 1. При перезагрузке Redis:
# - Читает dump.rdb из диска
# - Восстанавливает все ключи и значения в памяти
# - Сервер готов к работе
import subprocess
import time
# Остановка Redis
subprocess.run(["redis-cli", "SHUTDOWN"])
print("Redis остановлен")
time.sleep(2)
# Запуск Redis (восстановление из dump.rdb)
subprocess.Popen(["redis-server"])
print("Redis запущен, восстановление из снимка...")
time.sleep(2)
# Проверка восстановления
from redis import Redis
redis = Redis()
value = redis.get("key:0")
print(f"Восстановленное значение: {value}") # value_0
Преимущества и недостатки снимков
Преимущества:
- Компактное представление (бинарный формат)
- Быстрое восстановление
- Низкий overhead во время создания (BGSAVE)
- Полный снимок состояния
Недостатки:
- Потеря данных между снимками
- Использует много памяти (fork создаёт копию)
- Может занимать длительное время на больших БД
- Нет гарантии последовательности
Альтернатива: AOF (Append-Only File)
# В redis.conf:
"""
# Включить AOF
appendonly yes
# Имя файла
appendfilename "appendonly.aof"
# Синхронизация на диск:
# always — после каждой операции (медленно, надёжно)
# everysec — раз в секунду (по умолчанию)
# no — зависит от OS
appendfsync everysec
"""
# AOF содержит все команды:
"""
appendonly.aof:
*3\r\n
SET\r\n
key:1\r\n
value_1\r\n
*3\r\n
SET\r\n
key:2\r\n
value_2\r\n
*2\r\n
DEL\r\n
key:1\r\n
"""
Гибридный подход
# Использование обоих механизмов одновременно
# redis.conf:
"""
# RDB снимки каждые 15 минут
save 900 1
# AOF для дополнительной надёжности
appendonly yes
appendfsync everysec
"""
# Это обеспечивает:
# - Быстрое восстановление (RDB)
# - Минимальную потерю данных (AOF)
Практический пример
from redis import Redis
import time
import signal
import sys
class RedisPersistence:
def __init__(self):
self.redis = Redis(host="localhost", port=6379)
def create_snapshot(self):
"""Создать снимок"""
print("Создание снимка...")
self.redis.bgsave()
while True:
info = self.redis.info('persistence')
if info['rdb_bgsave_in_progress']:
print(".", end="", flush=True)
time.sleep(0.5)
else:
print("\nСнимок создан!")
break
def check_snapshot_info(self):
"""Получить информацию о снимке"""
info = self.redis.info('persistence')
return {
"last_save_time": info['rdb_last_save_time'],
"changes_since_save": info['rdb_changes_since_last_save'],
"file_size": info.get('rdb_current_bgsave_time', 'N/A')
}
def estimate_memory(self):
"""估ить использование памяти"""
info = self.redis.info('memory')
used_mb = info['used_memory'] / 1024 / 1024
peak_mb = info['used_memory_peak'] / 1024 / 1024
return {
"used_mb": used_mb,
"peak_mb": peak_mb
}
persist = RedisPersistence()
# Заполнение данных
for i in range(100000):
persist.redis.set(f"data:{i}", f"value_{i}" * 10)
# Создание снимка
persist.create_snapshot()
# Информация
info = persist.check_snapshot_info()
print(f"Информация о снимке: {info}")
memory = persist.estimate_memory()
print(f"Использование памяти: {memory['used_mb']:.1f}MB")
Синхронизация снимков в кластере
# Redis Sentinel следит за снимками
# и синхронизирует их между мастером и репликами
# sentinel.conf:
"""
sentinel monitor mymaster 127.0.0.1 6379 1
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
"""
# При failover снимок синхронизируется автоматически
Снимки в Redis — критический механизм для обеспечения durability и восстановления после сбоев.