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

Что такое Redis?

1.3 Junior🔥 211 комментариев
#Базы данных#Кэширование

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

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

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

Redis: In-Memory Data Store

Redis — это высокопроизводительное хранилище данных в памяти (in-memory data store), которое работает как сервис «ключ-значение» с поддержкой различных структур данных и расширенными возможностями.

Основные характеристики

1. Хранение в памяти (RAM)

  • Все данные хранятся в оперативной памяти сервера
  • Это обеспечивает наносекундную скорость доступа
  • Значительно быстрее чем диск-базированные БД

2. Типы данных

// Строки (Strings)
SET key "value"
GET key
APPEND key " more"
INCR counter

// Списки (Lists) — упорядоченные последовательности
LPUSH mylist "a"
RPUSH mylist "b"
LRANGE mylist 0 -1 // [a, b]

// Хэши (Hashes) — словари
HSET user:1 name "John"
HSET user:1 email "john@example.com"
HGETALL user:1 // {name: John, email: john@example.com}

// Множества (Sets) — уникальные значения
SADD tags "go" "redis" "database"
SMEMBERS tags

// Отсортированные множества (Sorted Sets)
ZADD scores 10 "player1"
ZADD scores 20 "player2"
ZRANGE scores 0 -1 WITHSCORES

Применение в Go

package main

import (
    "context"
    "fmt"
    "github.com/redis/go-redis/v9"
)

func main() {
    // Подключение к Redis
    rdb := redis.NewClient(&redis.Options{
        Addr: "localhost:6379",
    })
    defer rdb.Close()
    
    ctx := context.Background()
    
    // Установка значения
    err := rdb.Set(ctx, "user:1:name", "John Doe", 0).Err()
    if err != nil {
        panic(err)
    }
    
    // Получение значения
    val, err := rdb.Get(ctx, "user:1:name").Result()
    if err != nil {
        panic(err)
    }
    fmt.Println("Name:", val) // Name: John Doe
    
    // Установка с TTL (время жизни)
    rdb.Set(ctx, "session:abc123", "user_data", 3600*time.Second)
    
    // Список операций
    rdb.LPush(ctx, "queue", "task1")
    rdb.LPush(ctx, "queue", "task2")
    
    tasks, err := rdb.LRange(ctx, "queue", 0, -1).Result()
    fmt.Println("Tasks:", tasks) // [task2, task1]
}

Основные сценарии использования

1. Кэширование

func GetUserFromCache(userID string) (User, error) {
    ctx := context.Background()
    
    // Пытаемся получить из кэша
    cached, err := rdb.Get(ctx, "user:"+userID).Result()
    if err == nil {
        // Найден в кэше
        return parseUser(cached), nil
    }
    
    // Не в кэше, берём из БД
    user, err := db.GetUser(userID)
    if err != nil {
        return User{}, err
    }
    
    // Кэшируем на 1 час
    rdb.Set(ctx, "user:"+userID, user.JSON(), time.Hour)
    
    return user, nil
}

2. Сессии пользователя

func CreateSession(userID string, data map[string]interface{}) string {
    sessionID := uuid.NewString()
    
    // Сохраняем сессию с TTL
    rdb.HSet(ctx, "session:"+sessionID, data)
    rdb.Expire(ctx, "session:"+sessionID, 24*time.Hour)
    
    return sessionID
}

func GetSession(sessionID string) (map[string]interface{}, error) {
    return rdb.HGetAll(ctx, "session:"+sessionID).Result()
}

3. Подсчёт и рейтинги

func IncrementUserScore(userID string, points int) error {
    return rdb.IncrBy(ctx, "user:"+userID+":score", int64(points)).Err()
}

func GetLeaderboard() ([]string, error) {
    // Получить топ-10 игроков поScore
    return rdb.ZRevRange(ctx, "leaderboard", 0, 9).Result()
}

4. Очереди задач

func EnqueueTask(task Task) error {
    return rdb.LPush(ctx, "tasks:pending", task.JSON()).Err()
}

func ProcessTask() (Task, error) {
    jsonStr, err := rdb.RPop(ctx, "tasks:pending").Result()
    if err != nil {
        return Task{}, err
    }
    return parseTask(jsonStr), nil
}

5. Rate limiting

func IsRateLimited(userID string, limit int, window time.Duration) bool {
    key := "ratelimit:" + userID
    
    count, err := rdb.Incr(ctx, key).Result()
    if err != nil {
        return true // На случай ошибки Redis
    }
    
    if count == 1 {
        rdb.Expire(ctx, key, window)
    }
    
    return count > int64(limit)
}

Преимущества Redis

  • Скорость — операции в наносекундах
  • Простота — простой протокол, легко использовать
  • Гибкость — множество структур данных
  • Персистентность — возможность сохранения на диск (RDB, AOF)
  • Репликация — master-slave репликация для надёжности
  • Clustering — масштабирование горизонтально

Ограничения

  • Память — все данные в RAM, размер ограничен памятью сервера
  • Не ACID — не все операции являются транзакциями
  • Потеря данных — при отключении питания (если нет персистентности)

Персистентность

RDB (Redis Database) — снимок памяти

SAVE — синхронное сохранение (блокирует Redis)
BGSAVE — асинхронное сохранение в фоне

AOF (Append Only File) — логирование операций

APPENDONLY yes — включить AOF
APPENDFSYNC always|everysec|no

Кластеризация и высокая доступность

// Redis Cluster
rdb := redis.NewClusterClient(&redis.ClusterOptions{
    Addrs: []string{
        "localhost:7000",
        "localhost:7001",
        "localhost:7002",
    },
})

// Redis Sentinel (для failover)
rdb := redis.NewFailoverClient(&redis.FailoverOptions{
    MasterName: "mymaster",
    SentinelAddrs: []string{
        "localhost:26379",
    },
})

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