Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Redis: Назначение и применение
Что такое Redis
Redis (Remote Dictionary Server) — это высокопроизводительное хранилище данных в памяти (in-memory data store), которое работает по модели ключ-значение. Это одно из самых популярных и быстрых решений для кеширования и обработки данных в реальном времени.
Основные характеристики
Скорость:
- Работает в памяти (RAM), что обеспечивает микросекундную задержку
- Быстрее традиционных баз данных в 10-100 раз
- Идеален для высоконагруженных систем
Структуры данных:
- Строки (strings)
- Списки (lists)
- Множества (sets)
- Упорядоченные множества (sorted sets)
- Хэши (hashes)
- Битовые массивы (bitmaps)
- HyperLogLog для вероятностных подсчётов
- Потоки (streams) для обработки событий
Атомарность:
- Все операции выполняются атомарно
- Гарантирует консистентность данных
- ACID-подобное поведение
Основные применения
Кеширование
import redis
r = redis.Redis(host='localhost', port=6379)
# Установка значения с TTL (время жизни)
r.set('user:123:email', 'john@example.com', ex=3600) # 1 час
# Получение значения
email = r.get('user:123:email')
# Проверка существования
if r.exists('user:123:email'):
print('Найдено в кеше')
else:
print('Не найдено, нужно запросить из БД')
# Удаление
r.delete('user:123:email')
Сессии пользователей
# Сохранение данных сессии
session_data = {
'user_id': 123,
'username': 'john',
'logged_in_at': '2026-03-26 10:30:00',
'permissions': 'admin'
}
r.hset('session:abc123xyz', mapping=session_data, ex=86400) # 24 часа
# Получение всех данных сессии
session = r.hgetall('session:abc123xyz')
# Получение конкретного поля
user_id = r.hget('session:abc123xyz', 'user_id')
Счётчики и метрики
# Счётчик просмотров
r.incr('page:home:views') # Увеличить на 1
r.incrby('page:home:views', 5) # Увеличить на 5
# Получение значения
views = int(r.get('page:home:views'))
# Счётчик активных пользователей
r.sadd('active_users:today', 'user:123') # Добавить в множество
r.sadd('active_users:today', 'user:456')
# Количество активных пользователей
active_count = r.scard('active_users:today')
print(f'Активных пользователей: {active_count}')
Очереди задач
# Добавление задачи в очередь
task = {'id': 1, 'type': 'email', 'to': 'user@example.com'}
r.rpush('task_queue', str(task)) # Добавить в конец
# Обработка задач
while True:
task = r.lpop('task_queue') # Получить из начала (FIFO)
if task:
print(f'Обработка: {task}')
else:
print('Нет задач')
break
# Блокирующее получение (ждёт, пока появится элемент)
task = r.blpop('task_queue', timeout=30) # Ждёт до 30 сек
Рейтинг-листы (Leaderboards)
# Добавление очков пользователей в отсортированное множество
r.zadd('game:leaderboard', {'player1': 100, 'player2': 200, 'player3': 150})
# Увеличение очков
r.zincrby('game:leaderboard', 50, 'player1')
# Получение топ-10 игроков
top_10 = r.zrevrange('game:leaderboard', 0, 9, withscores=True)
for rank, (player, score) in enumerate(top_10, 1):
print(f'{rank}. {player}: {int(score)} очков')
# Позиция игрока
position = r.zrevrank('game:leaderboard', 'player1')
print(f'Позиция: {position + 1}')
Временные метки и события
# Отслеживание последних событий (streams)
# Добавление события
r.xadd('events:log', {'event_type': 'login', 'user_id': 123, 'timestamp': '2026-03-26 10:30:00'})
r.xadd('events:log', {'event_type': 'purchase', 'user_id': 123, 'amount': 99.99})
# Получение всех событий
events = r.xrange('events:log')
for event_id, data in events:
print(f'ID: {event_id}, Данные: {data}')
# Чтение с определённой позиции (для потребителей)
recent = r.xrevrange('events:log', count=5) # Последние 5 событий
Распределённые блокировки
# Установка блокировки (мьютекс)
lock_acquired = r.set('lock:resource:123', 'locked', nx=True, ex=10)
if lock_acquired:
try:
print('Блокировка получена, выполняю операцию...')
# Критическая секция
process_resource(123)
finally:
r.delete('lock:resource:123')
else:
print('Ресурс заблокирован другим процессом')
Публикация/Подписка (Pub/Sub)
# Подписчик
def subscriber():
pubsub = r.pubsub()
pubsub.subscribe('notifications')
for message in pubsub.listen():
if message['type'] == 'message':
print(f'Получено: {message["data"]}')
# Издатель
def publisher():
r.publish('notifications', 'Новое уведомление!')
r.publish('notifications', 'Ещё уведомление!')
Применение в Data Engineering
Кеширование результатов запросов:
def get_user_profile(user_id):
cache_key = f'user_profile:{user_id}'
# Проверяем кеш
cached = r.get(cache_key)
if cached:
return json.loads(cached)
# Если не в кеше, запрашиваем БД
user = db.query(f'SELECT * FROM users WHERE id = {user_id}')
# Сохраняем в кеш на 1 час
r.setex(cache_key, 3600, json.dumps(user))
return user
Агрегация данных в реальном времени:
# Подсчёт событий по категориям
def process_event(event):
category = event['category']
timestamp = event['timestamp']
date = timestamp.date()
# Увеличить счётчик
r.hincrby(f'events:{date}:{category}', 'count', 1)
r.hincrby(f'events:{date}:{category}', 'last_update', int(time.time()))
# Получить агрегаты
stats = r.hgetall(f'events:2026-03-26:purchase')
print(f"Покупок: {stats['count']}")
Когда использовать Redis
Redis хорошо подходит для:
- Кеширования часто запрашиваемых данных
- Сессионного хранилища
- Счётчиков и метрик
- Очередей задач
- Real-time систем
- Рейтинг-листов и топов
- Распределённых блокировок
- Pub/Sub систем
Когда Redis НЕ подходит:
- Для долгосрочного хранения (нужна персистентность)
- Когда объём данных больше доступной памяти
- Для сложных аналитических запросов
- Когда нужна полная ACID гарантия
Персистентность
Redis может сохранять данные на диск двумя способами:
- RDB (Redis Database) — снимки состояния (быстро, может потерять данные)
- AOF (Append-Only File) — логирование операций (безопаснее, медленнее)
Заключение
Redis — это essential инструмент для современного Data Engineering. Он обеспечивает скорость кеширования, помогает с очередями обработки, хранит счётчики и метрики, и интегрируется с большинством фреймворков и языков программирования. Понимание Redis критично для разработки высоконагруженных систем.