---
title: "Знакомство: зачем Go-сервису Redis"
description: "Разбираемся, зачем нужен redis в go-сервисе: кэш, сессии, счётчики и очереди на живых примерах, сравнение с Memcached и Postgres, границы применимости."
course: "Redis в Go: кэш, сессии и очереди на go-redis"
url: "https://golangmaster.ru/courses/go-redis/lessons/01-znakomstvo-go-redis/"
published: "2026-09-19"
updated: "2026-09-21"
minutes: 16
---

# Знакомство: зачем Go-сервису Redis

*Курс «Redis в Go: кэш, сессии и очереди на go-redis», урок 1 из 25. ~16 минут. Обновлено 21.09.2026. Источник: https://golangmaster.ru/courses/go-redis/lessons/01-znakomstvo-go-redis/*

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

Сценарий знакомый каждому, кто поддерживал продакшен: Go-сервис с одним Postgres, всё работает — до первой волны нагрузки. Страница профиля дёргает базу пять раз за рендер, отчёт на главной собирает агрегаты по секундам, а ночами ботовой трафик перемалывает одни и те же запросы, которые час назад уже были посчитаны. База честно отрабатывает каждую просьбу заново, CPU растёт, p95 ползёт вверх, и из кода виден единственный путь — добавить памяти Postgres. При этом половина этих вычислений вообще не обязана быть точной до миллисекунды: топ статей за час, сессия пользователя, лимит запросов к API — это данные, которые живут недолго, а читаются часто. Для них в архитектуре любого зрелого бэкенда есть второй этаж — быстрое хранилище в памяти. В экосистеме Go этим этажом почти всегда становится Redis, а его клиентом — библиотека go-redis, через которую мы будем работать весь курс. Полный план из двадцати пяти уроков лежит на [странице курса](/courses/go-redis/); здесь же — карта местности без лишней теории.

### Что такое Redis: хранилище в памяти для Go

Redis — сервер баз данных, который держит данные в оперативной памяти, а не на диске: чтение и запись выполняются за доли миллисекунды, тогда как даже хорошо настроенная дисковая СУБД отвечает за миллисекунды и медленнее. Команды Redis обрабатываются по одной, в одном потоке: параллельные запросы от вашего Go-приложения выстраиваются в очередь, зато каждая операция атомарна — два инкремента счётчика из разных горутин не затрут друг друга, мьютексы не понадобятся. Отсюда два практических следствия. Первое: пропускная способность одного инстанса ограничена одним ядром, хотя на обычном железе это десятки и сотни тысяч простых операций в секунду — для кэша и сессий хватает почти всегда. Второе: длинные команды блокируют всех, поэтому перебор всей базы через KEYS или гигантские значения в Redis не тащат. Данные при этом не обязаны исчезать при перезагрузке: Redis умеет сохранять снимки на диск (RDB) и вести журнал изменений (AOF), после рестарта он восстанавливает состояние. Но помнить стоит главное: Redis — про скорость и недолговечные данные, а не про гарантии хранения.

> **Не замена Postgres — сосед.** Память дороже диска, а полную гарантию сохранности Redis не даёт: при аварии теряется всё, что не попало в последний снимок или журнал. Поэтому схема всегда одна: СУБД — источник правды, Redis — быстрая надстройка рядом. Записали заказ в Postgres, его же копию на время положили в Redis.

### Зачем нужен redis: пять ролей в бэкенде

Вопрос «зачем нужен redis» честнее отвечать задачами, а не определениями. Первая роль — кэш: тяжёлый SQL-запрос или ответ внешнего API кладётся в Redis на десять минут, и из десяти тысяч обращений до базы доходит десяток. Вторая — сессии: пользователь логинится, сервер пишет его данные в Redis, и любой из пяти инстансов бэкенда достаёт сессию по cookie — состояние больше не привязано к конкретной машине, балансировщик крутит трафик как хочет. Третья — счётчики и лимиты: просмотры статьи, попытки входа, rate limit — атомарные операции в один поток делают это безопасно и без блокировок. Четвёртая — очереди: списки и потоки Redis превращаются в простой механизм фоновых задач ровно до того момента, когда нагрузка оправдает Kafka. Пятая — рейтинги и тренды: сортированные множества хранят топ игроков с обновлением очка за одну команду. Заметьте закономерность: везде данные читаются часто, живут недолго и допускают восстановление после потери. Как только задача перестаёт этим свойствам соответствовать — возвращаемся в Postgres и не геройствуем.

### Роли Redis одним списком

- Кэш запросов и ответов: база получает десяток обращений вместо десяти тысяч.
- Сессии пользователей: состояние не привязано к конкретному инстансу бэкенда.
- Счётчики и лимиты: атомарный INCR без мьютексов и гонок.
- Очереди задач: списки и Streams как простой producer-consumer.
- Pub/Sub: рассылка событий всем подписчикам в реальном времени.
- Рейтинги и топы: сортированные множества с обновлением очка за одну команду.

### Первый взгляд: go-redis в пяти строках

```go
package main

import (
    "context"
    "fmt"
    "time"

    "github.com/redis/go-redis/v9"
)

func main() {
    rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
    ctx := context.Background()

    rdb.Set(ctx, "user:42:name", "Аня", time.Hour)
    name, _ := rdb.Get(ctx, "user:42:name").Result()

    fmt.Println(name) // Аня
}
```

Не разбирайте пока каждую строку — это телепорт вперёд. redis.NewClient создаёт клиент с адресом сервера, ctx — контекст, который go-redis v9 требует в каждом вызове, Set кладёт значение со сроком жизни час, Get достаёт его обратно. Установку клиента, подключение и Ping разбираем в следующем уроке, а строки и сроки годности — в четвёртом и пятом.

### Redis против Memcached и Postgres

С Memcached Redis сравнивают реже, чем десять лет назад, но вопрос живой. Memcached — многопоточный кэш ключ-значение: очень быстрый, предельно простой, без структур данных, персистентности и каналов событий. Он до сих пор хорош, когда нужен тупой гигантский кэш строк и ничего больше. Redis умеет то же самое плюс структуры, срок жизни ключей с точностью до миллисекунд, снимки и журналы, репликацию и Pub/Sub — и берёт за это один процесс вместо десятка. С Postgres сравнение вообще не о скорости: это инструменты для разных слоёв архитектуры. Postgres — источник правды с транзакциями, внешними ключами и диском; Redis — слой скорости для недолговечных данных. Типичный зрелый сервис живёт с тремя хранилищами: Postgres для данных, Redis для горячего, поисковый движок для текстового поиска. Практическое правило, которое я применяю на code review: если потеря данных из хранилища ломает бизнес — это база; если просто заставит пользователей перелогиниться — Redis.

### Три хранилища в одном сервисе

| Хранилище | Где живут данные | Сильная сторона | Типовая роль |
| --- | --- | --- | --- |
| Redis | память плюс снимки и журнал на диске | структуры данных, скорость, Pub/Sub | кэш, сессии, счётчики, очереди |
| Memcached | только память | многопоточный простой кэш строк | большой плоский кэш без структур |
| Postgres | диск, журнал WAL | транзакции, ограничения, SQL | источник правды |

### Кейс из продакшена: что пропадёт при перезапуске Redis

Кейс, после которого одна команда пересмотрела всю схему хранения. В Redis жили кэш и сессии — но туда же по привычке положили корзину неавторизованного пользователя и черновик заявки: это же временные данные, у них есть TTL. В пятницу вечером оркестратор пересоздал ноду, Redis поднялся с пустой памятью — снимки на диск не были настроены, потому что там ничего важного. Кэш пережил бы это молча: он обязан уметь холодный старт. Но корзины пропали вместе с черновиками, саппорт собрал десяток тикетов, а команда потратила выходные на разбор. Разделение простое до безобразия: всё, чья потеря вызывает тикет, пишется в Postgres до того, как попадёт в Redis; Redis держит только то, что восстанавливается само — пересчётом из базы или повторным запросом. Сессии на грани: потерять их можно, пользователь просто перелогинится, но решать это нужно осознанно, а не по остаточному принципу.

> **Кэш без TTL — самая дорогая ошибка новичка.** Положили кэш через Set без срока годности — и через месяц столкнулись с заполненной памятью: Redis упрётся в лимит maxmemory и начнёт выселять ключи по политике LRU, включая те, что вы считали постоянными, либо начнёт отвечать ошибками на записи. Диагноз ставится задним числом и стоит ночного дежурства. Правило простое: у каждого кэш-ключа есть срок годности; как его ставить — пятый урок курса.

### Клиент go-redis v9: стандарт в экосистеме Go

За Go-кодом Redis стоит библиотека go-redis: проект вырос из личного репозитория автора и в 2022 году переехал в организацию redis на GitHub — с тех пор путь импорта выглядит как github.com/redis/go-redis/v9, и клиент числится рекомендуемым самой Redis. Девятая мажорная версия сделала контекст обязательным параметром каждой команды — примерно как database/sql давно живёт с context в сигнатурах. Для нас это значит: старые туториалы с вызовами rdb.Get(key) без контекста описывают восьмую версию, и копировать их сигнатуры не стоит. Альтернативы существуют — redigo старше и ближе к ручной работе с протоколом, rueidis моложе и агрессивнее по производительности, — но по количеству проектов, документации и ответов на Stack Overflow go-redis держит первое место, поэтому курс построен на нём. Установка и первое подключение к Redis из Go — тема следующего урока, а пока закончим обзор меню второго кода.

### Три роли одной строкой

```go
// счётчик просмотров статьи
rdb.Incr(ctx, "views:article:7")

// очередь: задача в конец списка
rdb.RPush(ctx, "jobs", "send-email:42")

// рейтинг: очки игрока в сортированном множестве
rdb.ZAdd(ctx, "leaderboard", &redis.Z{Score: 1500, Member: "user:42"})
```

Это не программа, а меню: счётчик, очередь и рейтинг — по одной команде на роль. INCR атомарно увеличивает строку с числом, RPush кладёт задачу в конец списка, ZAdd записывает очко в сортированное множество. Каждый тип данных получит свой урок; здесь важно ощущение — типовая задача Redis решается одной строкой кода.

### Спорное мнение: не каждому Go-сервису нужен Redis

Спорное мнение, которое я защищаю на архитектурных созвонах: пока сервис один и трафик скромный, Redis можно не заводить вовсе. Инстанс — это не только память, но и новая точка отказа, мониторинг, бэкапы и ещё один участник дежурного чата; монолит вместо него держит горячие данные в карте с мьютексом, а тяжёлые запросы ускоряет индексом в Postgres. Граница применимости конкретная: как только инстансов становится два и больше, карта с мьютексом перестаёт работать — состояние нужно делить между процессами, и здесь Redis вне конкуренции. То же с фоновыми воркерами, [очередями задач](/courses/go-redis/lessons/11-spiski/) и распределёнными лимитами: один процесс решает их в памяти, несколько — уже про Redis. Проверка перед внедрением честная: назовите задачу, которую не решает текущая связка, и покажите, где она болит в цифрах. Ответа нет — не тащите второй этаж ради строчки в резюме.

### Проверка: скорость Redis

**Вопрос:** Почему Redis отвечает за доли миллисекунды?

- ✅ Данные живут в оперативной памяти
- Он сжимает ответы перед отправкой
- Использует GPU для вычислений
- Работает без сети на shared memory

Ответ почти целиком определяется памятью: чтение из RAM на порядки быстрее диска. Однопоточная обработка добавляет предсказуемости и атомарности, но главный фактор — данные в памяти, а не на устройстве хранения.

### Проверка: ключи без срока годности

**Вопрос:** Кэш-ключи положили без TTL. Что произойдёт через месяцы?

- Ничего, Redis чистит старые ключи сам
- ✅ Память закончится, начнутся выселения или отказы в записи
- Redis упадёт сразу после миллиона ключей
- Ключи удалятся через сутки автоматически

У ключей без срока годности нет механизма самоочистки: при заполнении памяти включается политика maxmemory — выселение по LRU/LFU или отказ в записи. Поэтому кэшу всегда ставят TTL — этому посвящён пятый урок.

### Что выведет программа?

```go
rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
ctx := context.Background()

rdb.Set(ctx, "greeting", "привет", 0)
val, err := rdb.Get(ctx, "greeting").Result()

fmt.Println(val, err)
```

**Что выведет программа?**

- ✅ привет <nil>
- <nil> redis: nil
- привет redis.Nil
- ошибка компиляции

Set записал строку, Get её вернул, ошибка равна nil — fmt печатает нулевую ошибку как <nil>. Если бы ключа не было, err стал бы redis.Nil: это отдельная история четвёртого урока, а не повод для паники.

### Соберите создание клиента

Допишите конструктор клиента, стандартный адрес и нулевую базу.

```go
rdb := redis.___(&redis.Options{
        Addr: "___:6379",
        DB:   ___,
})

rdb.Set(ctx, "greeting", "привет", 0)
```

Подсказка: Конструктор называется NewClient, стандартный адрес — localhost, нулевая логическая база — просто 0.

Правильные ответы в пропусках: `NewClient`, `localhost`, `0`

### Соберите скелет работы с Redis

Расставьте строки в порядке работы программы: контекст, клиент, запись, чтение, вывод, закрытие.

Правильный порядок строк:

1. `ctx := context.Background()`
2. `rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})`
3. `rdb.Set(ctx, "greeting", "привет", 0)`
4. `val, err := rdb.Get(ctx, "greeting").Result()`
5. `fmt.Println(val, err)`
6. `rdb.Close()`

### Карточки: знакомство с Redis

- **Redis** — Хранилище данных в памяти: кэш, сессии, счётчики, очереди. Команды обрабатываются в одном потоке, поэтому операции атомарны.
- **In-memory** — Данные живут в оперативной памяти — ответы за доли миллисекунды. Персистентность RDB/AOF есть, но базой-источником правды Redis обычно не делают.
- **TTL** — Time To Live — срок жизни ключа. По истечении Redis удаляет ключ сам. Кэш без TTL — путь к заполненной памяти.
- **go-redis** — Клиент Redis для Go: github.com/redis/go-redis/v9. В v9 каждая команда принимает context.Context.
- **Postgres против Redis** — Postgres — источник правды на диске с транзакциями; Redis — слой скорости для недолговечных данных. Соседи по архитектуре, а не конкуренты.
- **Выселение (eviction)** — Политика при заполнении maxmemory: LRU/LFU выбрасывает старые ключи. Причина, по которой кэшу нужен срок годности.

Карта собрана: Redis — это кэш, сессии, счётчики, очереди и рейтинги в одном процессе, а go-redis v9 — способ добраться до всего этого из Go. Дальше по порядку: в уроке про [установку и первое подключение](/courses/go-redis/lessons/02-ustanovka-i-podklyuchenie/) соберём main.go с Ping, потом пройдёмся по [типам данных Redis](/courses/go-redis/lessons/03-tipy-dannyh-redis/) и дойдём до кэширования запросов, которое связывает курс с работой базы через [GORM](/courses/gorm/). Одна оговорка о формате: песочница сайта не умеет сеть и TCP-сокеты, поэтому redis-код в уроках не запускается в браузере — для реальной практики нужен локальный Go и Redis в Docker, обе установки занимают минуты и разбираются в следующем уроке. Домашнее задание — как раз про окружение.

## Коротко: что запомнить

- Redis — хранилище в памяти: доли миллисекунды на операцию, один поток, атомарные команды.
- Главные роли: кэш, сессии, счётчики, очереди, Pub/Sub и рейтинги на ZSET.
- Postgres остаётся источником правды; Redis — слой скорости для недолговечных данных.
- Memcached — простой кэш строк; Redis добавляет структуры данных, TTL, персистентность и каналы.
- Клиент по умолчанию — go-redis v9 с контекстом в каждой команде.
- Кэш без TTL — источник утечки памяти: maxmemory и выселения придут за вами.
- Песочница не запускает redis-код: нужен локальный Go и Redis в Docker.

## Домашнее задание

Подготовьте площадку: поставьте Go с go.dev и запустите Redis одной командой Docker — docker run --name go-redis-course -p 6379:6379 -d redis:7. Проверьте связь через docker exec -it go-redis-course redis-cli ping: в ответ должен прийти PONG. Песочница сайта для этого не подойдёт — нужен локальный запуск.

## Вопросы и ответы по уроку

### Можно ли использовать Redis как основную базу данных?

Технически да — персистентность RDB и AOF существует, но по умолчанию Redis терпит потерю последних секунд данных и держит всё в памяти. Для заказов, платежей и профилей источником правды остаётся СУБД на диске вроде Postgres; Redis — слой скорости рядом с ней.

### Сколько операций в секунду выдерживает Redis?

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

### Почему go-redis, а не redigo или rueidis?

go-redis — рекомендуемый клиент с самой большой базой проектов и ответов; v9 даёт единый API с контекстом в каждой команде. Redigo ближе к ручной работе с протоколом, rueidis агрессивнее по производительности, но для обучения и типовых сервисов экосистема go-redis практичнее.
