Кешування транзакцій та ігрових результатів: Підходи та ризики
1) Навіщо кешувати і де це дійсно потрібно
Кеш - інструмент зниження латентності і навантаження на ядро. У iGaming це критично для:- Читання балансів і статусів транзакцій (часті GET-запити);
- Історії ігор/спінів і агрегатів (верхівки лідерборда, останні N результатів);
- Метаданих ігор/провайдерів, лімітів ставок, статичних довідників;
- Фідів коефіцієнтів і «швидких» довідок для UX (банери, промо-статуси).
Але кеш ніколи не є джерелом істини для грошей і результатів. Істина - ledger/гаманець і підтверджені результати від провайдера.
2) Червона лінія: що кешувати не можна
Запис грошей: списання/зарахування балансу (операції запису) - тільки через БД/ledger з транзакціями та ідемпотентністю.
Рішення по ставці/виграшу до підтвердження провайдера.
KYC/AML і комплаєнс-прапори, що впливають на виплати.
Секрети/токени (кеш в пам'яті процесу допустимо, але не загальний кеш).
3) Базові патерни кешування
Cache-aside (lazy): додаток спочатку шукає в кеші, при промаху - читає з БД і кладе в кеш ('get → miss → load → set'). Універсальний і безпечний для читання.
Write-through: запис в БД проходить через кеш; забезпечує актуальність ключа, але підвищує латентність запису.
Write-behind (write-back): запис спочатку в кеш, потім асинхронно в БД. Заборонений для грошей/результатів - ризик втрати при падінні.
Read-through: кеш сам знає, як дістати з БД (проксі-кеш, наприклад, Redis with modules/sidecar). Хороший для метаданих.
Рекомендація: cache-aside для читань, write-through тільки там, де безпечно, write-behind - ніколи для грошових/ігрових істин.
4) Консистентність та ідемпотентність
Джерело істини: ledger (append-only), операції з'operation _ id'та ідемпотентною обробкою.
Баланс: читаємо з кешу, але будь-яку розбіжність підтверджуємо з бази перед критичними діями (депозит/виведення/велика ставка).
Інвалідація: при успішному записі в БД → del/expire відповідних ключів балансу/статусу.
Дедуплікація: outbox/inbox + idempotency keys для вебхуків/платежів; кеш не бере участі в дедупі, він тільки прискорює читання.
5) TTL, інвалідація та «право на застарівання»
Short-TTL для балансу: 1-5 секунд (або soft-TTL з background refresh).
Статуси транзакцій: короткий TTL (5-30 с) з активною інвалідацією по подіям ('deposit _ completed','settled').
Історія ігор: TTL 1-10 хвилин, інвалідація по події'new _ round'.
Метадані/довідники: TTL 10-60 хвилин, warm-up при деплої.
Event-driven інвалідація: шина подій (Kafka/PubSub) публікує'wallet _ updated','bet _ settled','bonus _ changed'→ передплатники видаляють/оновлюють ключі.
6) Антишторм-патерни (шторм промахів і догон)
Request coalescing: один потік «веде» запит до бази, інші чекають (mutex per key).
Stale-while-revalidate: видаємо «злегка застаріле», паралельно оновлюємо в тлі.
Jitter для TTL: рандомізуйте TTL (± 20%), щоб ключі не закінчувалися одночасно.
Бек-офф на промахах: при постійних промахах/помилках - тимчасовий negative-cache (див. нижче).
7) Negative-caching і сірий кардинал помилок
Для «не знайдено» (наприклад, ще немає статусу транзакції) - короткий negative TTL 1-3 с.
Не кешуйте помилки БД/провайдера довше декількох секунд - інакше закріпіть аварію.
Введіть canary-ключі для спостережуваності: зростання частки negative-хітів - привід для алерта.
8) Структура ключів і сегментація
Іменування: `wallet:{userId}`, `txn:{txnId}:status`, `game:{provider}:{tableId}:last_results`, `leaderboard:{tournamentId}:top100`.
Сегменти/неймспейси за env/region/brand: `prod:eu:wallet:{userId}'- виключіть перетину і крос-регіонне сміття.
Обмежуйте кардинальність - особливо для лідербордів та історії.
9) Кеш на edge, в кластері і в пам'яті
Edge-кеш (CDN/WAF): тільки для неперсональних даних (ігрові метадані, публічні лідерборди, медіа). Параметри запитів - whitelist; захист від cache-busting.
Redis/Memcached (кластер): основа для персональних читань; включайте AOF/RDB-снапшоти, репліку і квоти.
In-process кеш: мікросекундний доступ для гарячих довідників; потрібні механізми інвалідації (broadcast, version key).
10) Грошові кейси: Безпечні прискорення
Баланс гравця
Читання: cache-aside с TTL 1–5 с.
Запис: транзакція в БД → del кешу балансу; при критичній дії (виведення/велика ставка) - «recheck from DB».
Антигонка: optimistic locking версії балансу.
Статус платежу
Сценарій: користувач тисне «оновити статус».
Рішення: cache-aside + negative TTL на «pending»/«unknown» 2–5 с; оновлення по вебхуку PSP → інвалідація.
Бонуси/вейджер
Агрегати (прогрес у%): кешуємо 10-30 с; інвалідація за подією'bet _ placed/settled'.
11) Ігрові кейси: швидкісний фронт без спотворень істини
Історія спінів/ставок
Останні N подій: кеш-список з обмеженням (наприклад, 100), TTL 1-10 хв, поповнення по події'round _ finished'.
Не можна показувати «виграш», поки немає підтвердження від провайдера → проміжний статус «pending».
Лайв-ігри (WebSocket)
Короткочасний кеш останніх повідомлень/стану столу на 1-3 с для швидко підключилися клієнтів.
Стейт-ключі сегментуйте по'tableId/market'.
Лідерборди
Precompute + кеш на 10-60 с; для масових апдейтів - батчеві оновлення і часткова інвалідація «вікон».
12) Ризики і як їх закрити
Подвійне списання/фантомні виграші: тільки читання з кешу; всі списання/зарахування - через БД та ідемпотентність.
Старі дані → суперечка з гравцем: короткі TTL, «сувора реальність» перед виплатою, прозорі статуси («очікує підтвердження»).
Спліт-брейн кеш-кластеру: кворум/сентінел, timeouts, відмова від write-behind.
Cache stampede на гарячих ключах: coalescing, jitter, stale-while-revalidate.
Кеш-інжекція/poisoning: строгі ключі, сигнатури/підпис для кешованих API-відповідей, канарські перевірки.
Приватність/PII: шифрування каналу (mTLS), заборона кешу на edge для персональних даних, короткі TTL, очищення при логауті.
13) Спостережуваність кеша
Метрики на кожен шар:- Hit/Miss ratio за категоріями ключів; redis_ops/sec, latency p95/p99, evictions, memory_usage.
- Канарські ключі: `cache_health:{segment}'- перевірка частки negative-кешу і часу оновлення.
- Логи: промахи «пачками», часті'del'по одному сегменту = ознака «галасливого» сервісу.
- Трейси: спани «cache get/set/del» з ключовими тегами (без PII).
14) Міні-архітектура (референс)
1. Додаток (API/WS) → Redis-кластер (TLS, auth).
2. Джерело істини: Wallet DB (ledger), Game results store.
3. Шина подій: `wallet_updated`, `bet_settled`, `promo_changed`.
4. Інвалідатор: підписувач на події →'del '/' set'гарячих ключів.
5. Edge-кеш: тільки публічні ресурси/лідерборди.
6. Спостережуваність: дашборди кеша, алерти по stampede, негативним хітам.
15) Політики TTL (зразкова матриця)
16) Зразковий псевдокод (безпечне читання балансу)
python def get_balance(user_id):
key = f"wallet:{user_id}"
bal = cache. get(key)
if bal is not None:
return bal промах: беремо з БД і кладемо з коротким TTL + jitter bal = db. get_wallet_balance(user_id)
cache. set(key, bal, ttl=randint(1,5))
return bal
def apply_transaction(op_id, user_id, delta):
атомарний запис в БД з ідемпотентністю if db. exists_op(op_id):
return db. get_result(op_id)
res = db. apply_ledger (op_id, user_id, delta) # транзакція cache. delete(f"wallet:{user_id}") # інвалідація return res17) Чек-лист продакшен-готовності
- Ясне розмежування: істина в БД, кеш - тільки для читань.
- Патерни: cache-aside для читань; write-behind заборонений.
- Подієва інвалідація: `wallet_updated`, `bet_settled`, `promo_changed`.
- Короткі TTL + jitter; negative-cache ≤ 3 с.
- Антишторм: coalescing, stale-while-revalidate.
- Сегментація ключів за env/region/brand; ліміт кардинальності.
- Спостережуваність: hit/miss, evictions, p95, alерты на stampede/negative-spikes.
- Edge-кеш тільки для публічних даних; персональні - тільки в Redis/TLS.
- Runbook: що робити при розсинхроні (forced refresh, тимчасове відключення кешу сегмента).
- Регулярні тести: навантаження на гарячі ключі, навчання stampede.
Резюме
Кеш в iGaming - це прискорювач читання, а не «друга база даних для грошей». Зберігайте істину в ledger, забезпечте ідемпотентність і подієву інвалідацію, тримайте короткі TTL і антишторм-механіку, розділяйте edge-кеш і персональні дані, стежте за метриками кешу. Так ви отримаєте швидке UX без «ілюзій виграшу», подвійних списань і регуляторних проблем.
