Кэш коэффициентов: версии и безопасное обновление
TTL не знает, что рынок изменился секунду назад. Разбираем version fence, ключи snapshot-кэша, suspend-first и роль TTL как страховки, а не как основного механизма актуальности.

срок жизни не знает, что рынок уже изменился
Для быстро меняющихся коэффициентов истечение времени — плохая основная стратегия. Кеш должен обновляться событием с версией. TTL остаётся предохранителем на случай, если запись больше не получает обновлений, но не определяет актуальность.
Ключ — часть модели данных
Ключ snapshot должен включать область уникальности provider/internal event и market. Ошибка scope опаснее маленького TTL: данные одного варианта начинают перетирать другой. Формат ключа фиксируется как контракт и тестируется на коллизии на наборах реальных идентификаторов.
Одна запись на рынок или на событие
Event-level snapshot удобен для чтения одной страницы, но каждое изменение переписывает большой объект. Market-level уменьшает write amplification, зато сборка страницы делает больше reads. Выбор зависит от формы доступа; общий ответ без профиля чтения здесь бесполезен.
Барьер версии против запоздавшей записи
Каждое обновление несёт monotonically comparable version в рамках market. Cache writer меняет snapshot только если incoming version новее. Suspend имеет тот же versioning и не обходится отдельной «быстрой» веткой, иначе поздний price update может снова активировать уже закрытый рынок.
Старое значение, которое выглядит свежим
Если updated_at ставится временем записи в кеш, повтор старого события делает stale data «свежей». В snapshot нужно различать provider/event version time и local written_at. Диагностика должна видеть оба значения.
Проверка ключа кэша до рабочей среде
Cache key стоит рассматривать как часть доменной модели. Если в нём потерян provider, market type, segment или другая значимая размерность, разные snapshots могут попасть в одну ячейку и выглядеть абсолютно валидно по TTL. Это опаснее обычного cache miss, потому что система отдаёт правдоподобно свежие, но чужие данные.
До запуска полезно выписать все измерения, которые влияют на identity объекта, и проверить cardinality на реальном каталоге. Version fence добавляет вторую защиту: запоздавшая запись с меньшей версией не должна перетирать более новый snapshot даже при корректном ключе.
- Покрыть ключ unit-тестами на соседних рынках и provider-сценариях.
- Логировать version и generated_at вместе с cache hit.
- Использовать TTL как страховку, а не как основной сигнал актуальности.
Проверка ключ кэша начинается с вопроса «что может измениться независимо?»
Если один market может suspend, пока соседний остаётся live, общий cache key на всё событие увеличивает blast radius. Если данные всегда читаются комплектом и обновляются одной версией, слишком мелкий key, наоборот, создаёт лишнюю координацию. Граница кэша должна следовать модели изменений, а не удобству сериализации.
Главный guardrail — version fence. Запоздавшая запись не получает право перезаписать более новую только потому, что пришла позже в wall-clock времени. Для LiveOddsTile это означает простое правило: компонент читает market state с версией и freshness, а внутреннее устройство cache остаётся за API.
Перед production полезен тест с переставленными ответами: сначала записать version 42, затем искусственно задержать version 41 и убедиться, что старая запись отвергнута.
Распределение возраста данных по активным рынкам
Полезно контролировать не средний age всех ключей, а распределение по активным live-market и отдельный count ключей без изменений дольше ожидаемого. На дежурстве это быстро показывает остановку конкретного сегмента потока.

Связанные разборы по той же архитектурной цепочке
Поток коэффициентов и событий: путь данных от поставщика до экрана
Из каких участков складывается доставка коэффициента в реальном времени и где появляются очереди, рассинхронизация и устаревшие данные.
Перейти к разбору →НадёжностьКак искать узкие места в потоковой спортивной системе
Как сравнивать участки потоковой системы по задержке, очередям и потерям данных, чтобы не оптимизировать участок, который не влияет на пользователя.
Перейти к разбору →АрхитектураСостояние спортивного события: счёт, фазы и завершение матча
Как связать счёт, таймер и фазы матча в модель состояний, обрабатывать поздние сообщения поставщика и не допускать невозможных переходов.
Перейти к разбору →Букмекерская логикаКнопка коэффициента: доступность, изменение цены и приостановка
Как проектировать кнопку коэффициента: изменение цены, приостановка, фокус, клавиатурное управление и понятные состояния после выбора пользователя.
Перейти к разбору →