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

Как работает Redis?

3.0 Senior🔥 171 комментариев
#Кэширование и NoSQL

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

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

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

Как работает Redis

Redis (REmote DIctionary Server) — это in-memory хранилище данных структурированного формата, работающее как сервер ключ-значение. Это один из самых быстрых способов кэширования и работы с высоконагруженными системами, используемый в миллионах приложений по всему миру.

Архитектура и основной принцип

Redis работает по простой схеме:

  1. Хранение в памяти — все данные находятся в RAM, что обеспечивает наносекундные операции чтения/записи
  2. Однопоточность — каждый запрос выполняется атомарно, исключая race conditions
  3. Сохранение на диск — периодическое сохранение для восстановления после перезагрузки
  4. Сетевой протокол — клиент подключается через TCP на порт 6379
Клиент (Java приложение)
    ↓
  TCP (RESP протокол)
    ↓
Redis сервер (однопоточный)
    ↓
  В памяти (RAM)
    ↓
  На диск (RDB/AOF)

Типы данных в Redis

Redis поддерживает 5 основных типов:

1. String (строки)

// Базовые операции
redisTemplate.opsForValue().set("user:123:name", "John");
String name = redisTemplate.opsForValue().get("user:123:name");

// Атомарные операции
redisTemplate.opsForValue().increment("counter"); // +1
redisTemplate.opsForValue().append("text", " added");

2. List (списки, очереди)

// Очередь задач
redisTemplate.opsForList().rightPush("tasks", "task1", "task2");
String task = redisTemplate.opsForList().leftPop("tasks");

// Блокирующая операция
String item = redisTemplate.opsForList().leftPop("queue", 10, TimeUnit.SECONDS);

3. Set (множества, уникальные значения)

// Пересечение, объединение
redisTemplate.opsForSet().add("users:online", "user1", "user2");
Set<String> online = redisTemplate.opsForSet().members("users:online");

Set<String> common = redisTemplate.opsForSet().intersect("set1", "set2");

4. Sorted Set (отсортированные множества, лидерборды)

// Рейтинговая таблица
redisTemplate.opsForZSet().add("leaderboard", "player1", 1000);
redisTemplate.opsForZSet().add("leaderboard", "player2", 1500);

// Топ 10 игроков
Set<String> top10 = redisTemplate.opsForZSet()
    .reverseRange("leaderboard", 0, 9);

5. Hash (хеши, объекты)

// Кэширование объекта
Map<String, String> user = new HashMap<>();
user.put("name", "John");
user.put("email", "john@example.com");

redisTemplate.opsForHash().putAll("user:123", user);
String email = redisTemplate.opsForHash().get("user:123", "email");

Механизм работы в памяти

Redis использует хеш-таблицы с оптимизацией для больших наборов данных:

// Redis внутри работает так:
// Ключ → Хеш значения → Указатель на объект в памяти

// Поиск ключа O(1) время!
String value = redis.get("key"); // Наносеконды

Когда памяти недостаточно, Redis может использовать эвикшн политики (LRU, LFU):

maxmemory-policy:
- noeviction: Отказываем новым данным
- allkeys-lru: Удаляем самые старые ключи
- allkeys-lfu: Удаляем редко используемые ключи
- volatile-lru: Удаляем с TTL, затем LRU

Сохранение данных: RDB и AOF

RDB (Redis Database)

# Снимок памяти в один момент времени
SAVE           # Синхронно (блокирует)
BGSAVE         # В фоновом потоке
# Результат: dump.rdb файл

Плюсы: быстрая загрузка, компактный файл
Минусы: теряются данные между снимками

AOF (Append-Only File)

# Логирование всех команд
COMMAND → AOF файл → Применяем при загрузке

# Различные стратегии fsync
appendfsync always    # Синхронно (медленно, безопасно)
appendfsync everysec  # Каждую секунду (баланс)
appendfsync no        # ОС решает (быстро, рискованно)

Плюсы: полная история, точное восстановление
Минусы: больший файл, медленнее загружается

Использование с Java (Spring)

@Configuration
public class RedisConfig {
    
    @Bean
    public LettuceConnectionFactory connectionFactory() {
        return new LettuceConnectionFactory();
    }
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate(
            LettuceConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setKeySerializer(new StringRedisSerializer());
        return template;
    }
}

@Service
public class CacheService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    public void cacheUser(User user) {
        redisTemplate.opsForValue().set(
            "user:" + user.getId(),
            user,
            Duration.ofHours(1)
        );
    }
    
    public User getUser(Long id) {
        return (User) redisTemplate.opsForValue()
            .get("user:" + id);
    }
}

Или с аннотациями

@Service
public class UserService {
    
    @Cacheable(value = "users", key = "#id")
    public User findById(Long id) {
        // Первый вызов — вычисляем
        return userRepository.findById(id);
        // Последующие вызовы — из Redis
    }
    
    @CacheEvict(value = "users", key = "#id")
    public void updateUser(User user) {
        userRepository.save(user);
    }
}

Сложные сценарии: Transactions и Pub/Sub

Транзакции

redisTemplate.execute((RedisCallback<Object>) connection -> {
    connection.multi();
    connection.set("key1".getBytes(), "value1".getBytes());
    connection.set("key2".getBytes(), "value2".getBytes());
    connection.exec(); // Атомарно
    return null;
});

Pub/Sub (очень осторожно!)

redisTemplate.convertAndSend("channel:events", "event data");

redisTemplate.getConnectionFactory()
    .getConnection()
    .subscribe(message -> {
        System.out.println("Received: " + message);
    }, "channel:events".getBytes());

Производительность и лучшие практики

  1. Используй батчинг — отправляй несколько команд сразу
  2. Выбери правильную типизацию — Hash вместо String для объектов
  3. Управляй TTL — удаляй старые кэши автоматически
  4. Мониторь память — используй INFO memory
  5. Кластеризуй при масштабировании — Redis Cluster
  6. Репликация — Master-Slave для высокой доступности

Redis — это не просто кэш, а мощная база данных в памяти, способная хранить структурированные данные и обеспечивать супербыструю обработку высоконагруженных приложений.

Как работает Redis? | PrepBro