← Назад к вопросам
Как решишь проблему медленного выполнения запроса
2.3 Middle🔥 211 комментариев
#Базы данных и SQL
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Как будет происходить попадание данных в базу данных в Redis
Определение
Redis — это in-memory data store (хранилище данных в памяти), а не traditio базама на диске. Данные хранятся в RAM и теряются при перезагрузке, если не сохранены на диск.
Архитектура Redis
Апликация (Java)
↓
Redis Client (Jedis, Lettuce)
↓
Redis Server (в памяти)
↓
Persistence (опционально)
├── RDB (снимок памяти)
└── AOF (журнал команд)
Как данные попадают в Redis
1. SET команда — основной способ
// Java код с Redis
import redis.clients.jedis.Jedis;
public class RedisExample {
public static void main(String[] args) {
// Подключаемся к Redis
Jedis jedis = new Jedis("localhost", 6379);
// 1. Отправляем SET команду
jedis.set("user:123:name", "John"); // key, value
// Что происходит:
// ┌─────────────┐
// │ Java Code │
// └──────┬──────┘
// │ SET user:123:name John
// ↓
// ┌─────────────────────────────────┐
// │ Redis Network Protocol (RESP) │
// │ *3\r\n$3\r\nSET\r\n$15\r\nuser:123:name\r\n$4\r\nJohn\r\n │
// └──────┬──────────────────────────┘
// │
// ↓
// ┌─────────────────────────────────┐
// │ Redis Server (localhost:6379) │
// │ Парсит команду │
// │ Сохраняет в hash table в памяти │
// │ Возвращает OK │
// └─────────────────────────────────┘
// 2. Получаем значение
String name = jedis.get("user:123:name");
System.out.println(name); // John
// 3. Удаляем
jedis.del("user:123:name");
jedis.close();
}
}
2. MSET команда — множественное добавление
jedis.mset(
"user:1:name", "Alice",
"user:2:name", "Bob",
"user:3:name", "Charlie"
);
// Все три пары добавляются атомарно
3. PUSH команда — добавление в очередь
// Добавление в list
jedis.lpush("queue", "task1"); // Вспомогательный в начало
jedis.rpush("queue", "task2"); // В конец
// Добавление в set
jedis.sadd("users", "alice", "bob", "charlie");
// Добавление в sorted set
jedis.zadd("leaderboard", 100, "alice"); // score, member
jedis.zadd("leaderboard", 95, "bob");
Хранение в памяти
Hash Table структура
Redis хранит данные в hash table:
┌─────────────────────────────────────┐
│ Redis Memory (RAM) │
├─────────────────────────────────────┤
│ "user:123:name" → "John" │
│ "user:123:age" → "30" │
│ "user:456:name" → "Alice" │
│ "config:timeout" → "5000" │
│ ... │
└─────────────────────────────────────┘
Разные типы данных
// String
jedis.set("key", "value");
// List (очередь)
jedis.lpush("mylist", "a", "b", "c");
// Результат: [c, b, a]
// Set (множество, без дубликатов)
jedis.sadd("myset", "a", "b", "a"); // a добавляется один раз
// Sorted Set (с порядком)
jedis.zadd("scores", 100, "player1");
jedis.zadd("scores", 95, "player2");
// Hash (объект с полями)
jedis.hset("user:123", "name", "John");
jedis.hset("user:123", "email", "john@example.com");
Сохранение на диск (Persistence)
1. RDB — Redis Database (снимок памяти)
# Конфигурация (redis.conf)
save 900 1 # Сохранить если 1 ключ изменился за 900 сек
save 300 10 # Сохранить если 10 ключей изменилось за 300 сек
save 60 10000 # Сохранить если 10000 ключей изменилось за 60 сек
# Процесс:
# 1. Redis создаёт fork процесса
# 2. Child процесс пишет snapshot в dump.rdb
# 3. Parent процесс продолжает обслуживать клиентов
// Java код
public class RedisPersistence {
public static void main(String[] args) {
Jedis jedis = new Jedis();
// Ручное сохранение
jedis.save(); // Синхронное (блокирует)
jedis.bgsave(); // Асинхронное (в фоне)
jedis.close();
}
}
2. AOF — Append Only File (журнал команд)
# Конфигурация (redis.conf)
appendonly yes
appendfsync everysec # Синхронизировать диск каждую секунду
# Результат (appendonly.aof):
SET user:123:name John
SET user:456:name Alice
DEL user:123:name
LPUSH queue task1
LPUSH queue task2
При перезагрузке Redis:
- Читает appendonly.aof
- Переиграет все команды
- Восстанавливает состояние
Скорость vs Надёжность
Метод Скорость Надёжность Когда использовать
──────────────────────────────────────────────────────────
No Persist. Максимальная Ноль Кеш (потеря OK)
RDB Очень быст. Хорошая Backup'ы, снимки
AOF Средняя Отличная Важные данные
RDB + AOF Медленная Отличная Production
Практический пример: Redis как Cache
@Service
public class UserService {
@Autowired
private Jedis redis;
@Autowired
private UserRepository db;
public User getUser(Long id) {
String cacheKey = "user:" + id;
// 1. Ищем в Redis
String cached = redis.get(cacheKey);
if (cached != null) {
return parseUser(cached); // Вернули из кеша
}
// 2. Не нашли — идём в БД
User user = db.findById(id).orElse(null);
if (user != null) {
// 3. Сохраняем в Redis
redis.setex(
cacheKey,
3600, // TTL = 1 час
serializeUser(user)
);
}
return user;
}
public void updateUser(Long id, User user) {
// 1. Обновляем в БД
db.save(user);
// 2. Инвалидируем кеш
redis.del("user:" + id);
}
}
Пропускная способность и задержка
Операция Задержка (latency) Пропускная способность
──────────────────────────────────────────────────────────────
SET ~0.1ms 100000+ операций/сек
GET ~0.1ms 100000+ операций/сек
LPUSH ~0.1ms 100000+ операций/сек
DEL ~0.1ms 100000+ операций/сек
Disk Write (RDB) ~10ms зависит от диска
Disk Write (AOF) ~1ms зависит от диска
Потеря данных
// Сценарий 1: No persistence
jedis.set("important", "data");
// Redis crashed → данные потеряны
// Сценарий 2: RDB (снимок каждые 60 секунд)
jedis.set("important", "data");
// Redis crashed через 30 сек → потеря данных
// Сценарий 3: AOF (синхронизация каждую секунду)
jedis.set("important", "data");
// Redis crashed через 0.5 сек → максимум потеря 0.5 сек
// Сценарий 4: AOF fsync=always (синхр. каждую операцию)
jedis.set("important", "data");
// Redis crashed сразу же → данные сохранены!
// Но медленнее
На собеседовании
"Redis хранит данные в памяти (RAM). Процесс:
- Java приложение отправляет команду (SET, LPUSH и т.д.)
- Redis парсит команду
- Данные добавляются в hash table в памяти
- Redis возвращает ОК
- Получение: GET, LPOP и т.д. читают из памяти
Persistence (опционально):
- RDB: периодически сохраняет снимок памяти на диск
- AOF: логирует все команды в файл
Без persistence данные теряются при перезагрузке!
Производительность: ~100k операций в секунду с задержкой ~0.1ms."