Caching Tranzacții și rezultate ale jocurilor: abordări și riscuri
1) De ce cache și în cazul în care aveți cu adevărat nevoie de ea
Cache este un instrument pentru reducerea latenței și a sarcinii pe miez. În iGaming, acest lucru este esențial pentru:- Citirea bilanțurilor și a statusurilor tranzacțiilor (solicitări frecvente GET);
- Istoria jocurilor/rotirilor și agregatelor (vârfurile clasamentului, ultimele rezultate N);
- Metadate ale jocurilor/furnizorilor, limite de pariere, directoare statice;
- Feed-uri de coeficienți și referințe „rapide” pentru UX (bannere, stări promoționale).
Dar cache-ul nu este niciodată sursa adevărului pentru bani și rezultate. Adevar - registru/portofel si rezultate confirmate de la furnizor.
2) Linia roșie: că nu puteți cache
Înregistrarea banilor: debitarea/creditarea soldului (operațiuni de înregistrare) - numai prin baza de date/registru cu tranzacții și idempotență.
Decizii de pariere/câștig înainte de confirmarea furnizorului.
Steagurile KYC/AML și de conformitate care afectează plățile.
Secretele/jetoanele (memoria cache în memoria de proces este validă, dar nu și memoria cache partajată).
3) Modele de caching de bază
Cache-deoparte (leneș): aplicația se uită mai întâi în memoria cache, dacă ratează, citește din baza de date și o pune în memoria cache ('get → miss → load → set'). Versatil și sigur de citit.
Write-through: scrierea la baza de date trece prin memoria cache; asigură că cheia este actualizată, dar crește latența înregistrării.
Write-back (write-back): scrierea mai întâi la memoria cache, apoi asincron la baza de date. Interzis pentru bani/rezultate - risc de pierdere la cădere.
Read-through: cache-ul în sine știe cum să iasă din baza de date (proxy cache, de exemplu, Redis cu module/sidecar). Bun pentru metadate.
Recomandare: cache-deoparte pentru citește, scrie-prin numai în cazul în care în condiții de siguranță, scrie-în spatele - niciodată pentru bani/adevăruri de joc.
4) Coerență și idempotență
Sursa adevărului: registru (numai pentru adăugare), operațiuni cu "operation _ id' și procesare idempotentă.
Balanță: citim din memoria cache, dar orice discrepanță este confirmată din baza de date înainte de acțiuni critice (depozit/retragere/rată mare).
Handicap: în cazul în care cheile de echilibru/stare corespunzătoare sunt scrise cu succes în baza de date → del/expiră.
Deduplicare: outbox/inbox + chei de idempotenta pentru carti web/plati; memoria cache nu participă la dedup, ci doar accelerează citirea.
5) TTL, handicap și „dreptul la obsolescență”
Short-TTL pentru echilibru: 1-5 secunde (sau moale-TTL cu refresh de fundal).
Statusurile tranzacției: scurt TTL (5-30 s) cu handicap activ prin evenimente ('deposit _ finalized', 'settled').
Istoria jocului: TTL 1-10 minute, handicap din cauza evenimentului „new _ round”.
Metadate/directoare: TTL 10-60 minute, warm-up atunci când epuizat.
Handicap bazat pe evenimente: event bus (Kafka/PubSub) publică 'wallet _ update', 'bet _ settled', 'bonus _ changed' → abonații șterg/actualizează cheile.
6) Modele anti-furtună (Miss Storm și Dogon)
Cerere de coalescing: un fir „conduce” cererea la baza de date, restul sunt în așteptare (mutex pe cheie).
Stale-în timp ce-revalidate: da afară „ușor depășit”, actualiza simultan în fundal.
Jitter pentru TTL: Randomize TTL (± 20%), astfel încât cheile nu expiră în același timp.
Back-off la ratări: cu ratări/erori constante - memorie cache negativă temporară (vezi mai jos).
7) Erori cardinale negative și gri
Pentru „nu a fost găsit” (de exemplu, nu există încă nici un statut de tranzacție) - un scurt TTL negativ 1-3 s.
Nu cache baza de date/erori furnizor pentru mai mult de câteva secunde - în caz contrar rezolva accidentul.
Introduceți cheile canare pentru observabilitate: o creștere a ponderii loviturilor negative este un motiv de alertă.
8) Structura și segmentarea cheilor
Именование: 'wallet: {userId}', 'txn: {txnId}: status', 'game: {provider}: {tableId}: last _ results',' leaderboard: {tournamentId}: top100 '.
Segmente/namespaces de env/region/brand: 'prod: eu: wallet: {userId}' - exclude intersecțiile și gunoiul transregional.
Limitați cardinalitatea - în special pentru clasamente și istorie.
9) Cache pe margine, în cluster și în memorie
Edge cache (CDN/WAF): numai pentru datele non-personale (metadate de joc, lideri publici, mass-media). Parametrii de interogare - lista albă; protecție cache-busting.
Redis/Memcached (cluster): baza pentru citiri personale; Includeți instantanee AOF/RDB, replica și cotele.
Memorie cache în proces: acces la microsecunde pentru directoare fierbinți; mecanisme de dezactivare (difuzare, versiune cheie) sunt necesare.
10) Cazuri de bani: accelerări sigure
Soldul jucătorului
Citește: cache-deoparte cu TTL 1-5 s.
Înregistrare: tranzacție în baza de date soldul → del cache; la o acțiune critică (ieșire/pariu mare) - „reverificați de la DB”.
Antigona: versiune optimistă de blocare a bilanțului.
Starea plății
Scenariu: utilizatorul apasă „stare de actualizare”.
Soluție: cache-deoparte + TTL negativ la „în așteptare „/” necunoscut „2-5 s; Actualizare PSP Webhook → dizabilitate.
Bonusuri/vager
Agregate (progres în%): cache 10-30 s; handicap din cauza evenimentului „bet _ plased/settled”.
11) Cazuri de joc: un front de mare viteză fără distorsiuni ale adevărului
Istoric rotiri/pariuri
Ultimele evenimente N: lista cache cu restricție (de exemplu, 100), TTL 1-10 minute, reaprovizionare prin evenimentul 'round _ finished'.
Nu puteți afișa „câștig” până când nu există confirmare din partea furnizorului → statutul intermediar este „în așteptare”.
Jocuri live (WebSocket)
Memoria cache pe termen scurt a mesajelor recente/starea tabelului timp de 1-3 secunde pentru clienții conectați rapid.
Chei de stat segment de 'tableId/market'.
Clasamente
Precompute + cache pentru 10-60 s; pentru actualizări de masă - actualizări de lot și dizabilitatea parțială a „ferestrelor”.
12) Riscuri și cum să le închideți
Dublu încărcare/fantomă câștigă: citire numai din memoria cache; toate taxele/creditele - prin DB și idempotence.
Date vechi → dispută cu jucătorul: scurt TTL, „realitate strictă” înainte de plată, statusuri transparente („în așteptarea confirmării”).
Split-creier cluster cache: cvorum/santinelă, timeout, refuza scrie-spate.
Cache busculadă pe taste fierbinți: coalescing, jitter, stale-în timp ce-revalidate.
Injecție/otrăvire cache: chei puternice, semnături/semnătură pentru răspunsuri API în cache, verificări canare.
Confidențialitate/PII: criptare canal (mTLS), interdicție cache pe margine pentru datele personale, scurt TTL, curățare logout.
13) cache observabilitate
Valori per strat:- Raportul Hit/Miss pe categorii cheie; redis_ops/sec, latenţă p95/p99, evacuări, memory_usage.
- Chei canare: 'cache _ health: {segment}' - verifică cota de memorie cache negativă și timpul de actualizare.
- Jurnale: ratează "în loturi", frecvent "del' pe un segment = un semn al unui serviciu" zgomotos ".
- Trasee: se întinde "cache get/set/del' cu tag-uri cheie (fără PII).
14) Mini-arhitectură (referință)
1. Aplicație (API/WS) → cluster Redis (TLS, auth).
2. Sursa adevărului: Portofel DB (registru), Magazin de rezultate ale jocului.
3. Bus eveniment: 'portofel _ actualizat', 'bet _ settled', 'promo _ changed'.
4. Dezactivat: → 'del'/' set' hot key event abonat.
5. Memorie cache Edge: numai resurse publice/consilii de conducere.
6. Observabilitate: tablouri de bord cache, alerte de busculadă, lovituri negative.
15) Politici TTL (matrice de probă)
16) Exemplu de cod Pseudo (echilibru sigur citit)
python def get_balance (user_id):
key = f „portofel: {user _ id}”
bal = cache. obține (cheie)
dacă bal nu este Niciunul:
return bal miss: luați-l din baza de date și puneți-l cu un scurt TTL + jitter bal = db. get_wallet_balance (user_id)
cache. set (cheie, bal, ttl = randint (1,5))
bal retur
def apply_transaction (op_id, user_id, delta):
intrarea atomică în baza de date cu idempotență dacă db. exists_op (op_id):
return db. get_result (op_id)
res = db. apply_ledger (op_id, user_id, delta) # tranzacție cache. delete (f „wallet: {user _ id}”) # disability return res17) Lista de verificare a pregătirii pentru producție
- Delimitare clară: adevărul în baza de date, memoria cache - numai pentru citiri.
- Modele: cache-deoparte pentru citește; scrierea în spate este interzisă.
- Handicap eveniment: 'portofel _ actualizat', 'bet _ settled', 'promo _ changed'.
- Scurt TTL + jitter; memorie cache negativă ≤ 3 с.
- Anti-furtună: coalescing, stale-în timp ce-revalidate.
- Segmentarea cheilor după env/regiune/marcă; limită de cardinalitate.
- Observabilitate: hit/miss, evacuări, p95, alerte pe busculadă/piroane negative.
- Memorie cache pentru date publice numai; personal - numai în Redis/TLS.
- Runbook: ce să faceți atunci când nu se sincronizează (reîmprospătare forțată, dezactivarea temporară a memoriei cache de segment).
- Teste regulate: sarcină cheie fierbinte, exerciții de ștanțare.
Rezumat reluare
Memoria cache din iGaming este un accelerator de lectură, nu o "a doua bază de date pentru bani. "Păstrați adevărul în registru, asigurați idempotența și dizabilitatea evenimentelor, păstrați mecanica scurtă TTL și anti-furtună, cache-ul de margine separat și datele personale, monitorizați valorile cache-ului. Deci, veți obține un UX rapid, fără „iluzia de a câștiga”, taxe duble și probleme de reglementare.
