Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Задачи

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про Redis : cache, memoization, component

Как использовать кеширование в системах, где ответы не повторяются для одного и того же пользователя?

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

Короткий ответ

Если полный ответ уникален, кешируют не “ответ целиком”, а его части: справочники, настройки, права, данные профиля, результаты тяжёлых подзапросов или промежуточные вычисления. Часто помогает кеш на уровне “строительных блоков”: отдельные сущности по ключу, а итоговый ответ собирается из них. Можно кешировать не данные, а “защиту от перегрузки”: лимиты, локальные prefetch, короткий TTL на часто запрашиваемые компоненты. Ещё один вариант — кешировать отрицательные результаты (например, “нет данных”) и использовать stale-данные при временных сбоях.

Длинный ответ

Почему кеш возможен даже при “уникальных ответах”

Уникальность итогового ответа не означает, что все вычисления внутри него уникальны. Обычно есть общие фрагменты, которые повторяются между пользователями или между запросами одного пользователя.

1) Кеширование по уровням: “части ответа” вместо “ответа”

Вместо ключа вида cache:user:<id>:full_response выбирают ключи для компонентов:

  • справочники (countries, currencies, categories)

  • настройки/фичи (feature_flags)

  • профиль пользователя (user_profile)

  • права/роли (user_permissions)

  • часто используемые сущности по id (товар, отель, город)

Сборка ответа тогда становится:

  1. взять несколько кусочков из кеша/БД

  2. склеить в ответ

2) Кеш промежуточных вычислений

Если есть дорогая операция (например, расчёт скоринга/фильтров):

  • кешируйте результат этой операции на короткий TTL

  • ключ строится по входным параметрам, а не по пользователю целиком

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

Пример идеи ключа:

  • score:<segment>:<param_hash>

3) Кеш “на чтение сущностей” + локальная дедупликация запросов

Частая проблема: несколько горутин одновременно запрашивают один и тот же ресурс.

Решение:

  • кеш сущностей в Redis с TTL

  • дедупликация “в полёте” (singleflight) внутри сервиса

Пример singleflight (коротко):

import "golang.org/x/sync/singleflight"

var g singleflight.Group

func getHotel(ctx context.Context, id string) (any, error) {
	v, err, _ := g.Do("hotel:"+id, func() (any, error) {
		// 1) попробовать Redis
		// 2) иначе БД
		// ... детали опущены
		return fetchFromDB(ctx, id)
	})
	return v, err
}

4) Кеширование “негативных” и “частичных” результатов

Иногда полезно кешировать:

  • “нет данных” (чтобы не долбить БД при пустых выдачах)

  • частичный результат (например, только список id, а детали догружаются отдельно)

Важно:

  • TTL для негативного кеша обычно короткий, чтобы не “залипнуть” на пустоте

5) Stale-while-revalidate и защита SLA

Определение: Stale-while-revalidate — можно отдать слегка устаревшие данные быстро, а обновление сделать в фоне.

Подход:

  • при истечении TTL не блокировать пользователя долгим пересчётом

  • отдавать “последнее значение”, а пересчёт запускать асинхронно

6) Практические правила, чтобы кеш не стал проблемой

  • измеряйте hit rate и latency

  • задавайте разумные TTL и лимиты размера

  • продумывайте инвалидацию: TTL + события, если есть стрим изменений

  • избегайте “кеша на миллионы уникальных ключей” без ограничений (память улетит)

Вывод

Если ответы уникальны, кешируют не ответ целиком, а переиспользуемые части и промежуточные вычисления, плюс применяют дедупликацию запросов и stale-стратегии. Это снижает нагрузку и стабилизирует latency даже без повторяемости полного ответа.

  • Аватар

    Golang Guru

    Maxim Lukyanov

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.

Уровень

  • Рейтинг:

    4

  • Сложность:

    7

Навыки

  • Redis

    Redis

Ключевые слова

#cache

#memoization

#component

Подпишись на Golang Developer в телеграм

  • Аватар

    Golang Guru

    Maxim Lukyanov

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.