TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #3008 1.87K
День 2505. #ЗаметкиНаПолях
Кэширование в Redis с Двойным Ключом. Начало
Кэширование в Redis — это просто… пока вы не осознаете, что вашей сущности нужны два разных ключа поиска: один внутренний и один внешний. Тут всё становится сложнее: если не быть внимательным, приложение может стать жертвой устаревших данных, пропущенных инвалидаций и несогласованного состояния между сервисами.

Проблема
Представьте, что вы разрабатываете типичное приложение. У каждого пользователя есть:
- UserId (GUID, внутренний, неизменяемый)
- Email (используется для входа, внешний, изменяемый)
Теперь рассмотрим, как система взаимодействует с этим профилем пользователя.

Вариант 1. Аутентификация (Email → User)
При входе в систему служба идентификации должна:
1. Найти пользователя по email;
2. Загрузить его учётные данные;
3. Загрузить его профиль (роли, настройки и т.п.)
Для этого требуется быстрый поиск по email. Выполнение этого SQL-запроса в часы пиковых нагрузок может замедлить систему. Redis решает эту проблему.

Но остальная бизнес-логика ведёт себя по-другому…

Вариант 2. Внутренние микросервисы (UserId → Профиль)
Биллинг, уведомления, аналитика и журналы аудита — все они идентифицируют пользователей по внутреннему UserId. Поэтому они ожидают быстрого поиска по UserId.

Если вы кэшируете только по одному ключу:
- UserId - трафик аутентификаций приводит к задержкам,
- Email - внутренние сервисы постоянно используют БД.

Кэширование с двойным ключом
Кэширование с двойным ключом позволяет получить доступ к одной и той же сущности, используя два разных ключа:
- По внутреннему, стабильному ключу (UserId),
- По внешнему, доступному пользователю, ключу (Email).

Но есть и более серьёзная проблема…
Наивный разработчик может сказать: «Просто храните полный JSON объекта под обоими ключами!»

Это сработает, на время. Но,
- если пользователь сменит email, нужно удалить запись со старым ключом;
- приходится удалять два элемента каждый раз при изменении пользовательских данных;
- сбои в работе сети между двумя вызовами StringSetAsync = повреждение кэша;
- вы тратите память, храня дублирующиеся JSON-объекты.

Поэтому профессиональные системы используют другой подход.

Единый источник данных + ключ индекса
Храним полный профиль пользователя ОДИН РАЗ:
user : data : {userId} → JSON


Храним индекс Email → UserId:
user : email : {email} → userId


Это обеспечивает:
- отсутствие дублирования JSON-данных,
- отсутствие несоответствий между первичными и вторичными ключами,
- безопасные обновления email,
- простую инвалидацию,
- производительный поиск в обоих случаях.

Далее посмотрим, как это реализовать в .NET.

Окончание следует…

Источник:
https://thecodeman.net/posts/dual-key-redis-caching-in-dotnet
  • 👍 20
More from @netdeveloperdiary
  1. Sep 29, 2026Фото 3 (с) Анатолий Кулаков
  2. Sep 29, 2026День 2799. Конференция DotNext 2026. Часть 1 25 и 26 сентября в Москве прошла очередная ко…
  3. Sep 28, 2026День 2798. #Оффтоп Утиная Типизация в C# с Помощью Перехватчиков. Часть 2 Некоторое время…
  4. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  5. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  6. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →