Strategie di cache
1) Perché memorizzare e dove farlo
Kesh è un livello di memoria veloce che riduce la latitudine e il carico di risorse costose (CPU/BD/API esterne). Obiettivi importanti:- Velocità (p95/p99 più bassa), costo (meno egress/CPU), stabilità (meno dipendenze sotto il picco).
- Alleggerimento dei picchi e isolamento dai vicini rumorosi.
1. Client (browser/mobile): cache HTTP, IndexedDB, storage locale.
2. Edge/CDN - I nodi POP sono più vicini all'utente e la cache di una parte dello statico e dell'API.
3. Gateway L7/Reverse-proxy - Nginx/Avvoy/Varnish (Microcesh, SWR).
4. La cache di servizio è Redis/Memcached all'interno del cluster.
5. Intra-processuale - in-memory (Caffeine/Guava/LRU-map).
6. Cache in database - Rappresentazioni materiali, indici secondari.
Regola: memorizzare il più vicino possibile al consumatore, ma conservare la verità.
2) Pattern di cache
2. 1 Cache-aside (“lazy loading”)
L'applicazione prima legge dalla cache. in caso di errore dalla fonte, poi scrive nella cache.
I vantaggi sono semplicità, controllo. Contrari: lanci freddi, finestre di disaccordo.
2. 2 Read-through
La lettura è sempre attraverso la cache che va all'origine quando fallisce (libreria/livello di procrastinazione).
È facile centralizzare i criteri TTL/serilizzazione.
2. 3 Write-through / Write-back (write-behind)
Write-through - Scrittura nella cache e sorgente sincrono coerenza superiore, latenza superiore.
Write-back - Scrittura nella cache, scrittura flash asincrona all'origine in modo rapido, ma rischi di perdita e conflitti.
2. 4 Refresh-ahead (proactive)
Prevale «presto scadrà TTL» e aggiorna la chiave di sfondo impedendo la stampa.
2. 5 Negative caching
La cache «nessun dato/404/vuoto» di TTL breve riduce il carico di lavoro della sorgente.
2. 6 Micro-caching
TTL molto breve (0. 5-5 c) su L7 per «quasi altoparlante» - riduce drasticamente le code.
3) HTTP-cash: intestazione e controllo
3. 1 Intestazioni di base
`Cache-Control`: `max-age`, `s-maxage` (для shared кэшей), `public/private`, `no-store`, `stale-while-revalidate`, `stale-if-error`.
Validi: «ETag» (hash di contenuto), «Last-Modified».
Richieste di condizioni: «If-None-Match», «If-Modified-Since» 304 Not Modified.
3. 2 Vary e chiavi
'Vary: Accept-Encoding, Authorization, Cookie, Accept-Language' - Crea diverse opzioni di cache. Minimizzate Vary per non far esplodere la cardinalità.
3. 3 Esempio di risposta HTTP
Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=60
ETag: "a1b2c3"
Vary: Accept-Encoding
4) Progettazione delle chiavi e TTL
4. 1 Chiavi
Struttura: 'tenant: user: {id}: profile: v3' (inclusa la versione dello schema).
Evitare il PII in chiave.
Per le raccolte, chiave + opzioni di query (normalizzate e ordinate).
4. 2 TTL e coerenza
TTL breve riduce la coerenza, ma aumenta gli errori.
I dati critici sono validi ('ETag') e SWR (stale-while-revalidate).
Per chi cambia raramente, è una lunga TTL + bomber invalidanti.
4. 3 Versioning/basting
Se le modifiche non sono compatibili, cambia il prefisso/versione della chiave ('v2' v3 ').
Per le risorse statiche - content hash nel nome del file.
5) Disabilità: strategie e pratiche
5. 1 Eliminazione diretta
«DEL key »/« PURGE» sul proxy. Pericolo: corse tra cancellazioni e lettori multipli.
5. 2 Tag/Surrogate keys
Associare il documento a un insieme di tag (categoria/autore). La disabilità è un tag.
В Varnish/Edge — `Surrogate-Key: article:42 tag:author:7` + `BAN tag:author:7`.
5. 3 Event-driven invalidità
Pub/Sub (Kafka/NATS) - Quando cambia l'origine, pubblichiamo l'evento «invalidate».
I computer della cache ascoltano e rimuovono o aggiornano le chiavi.
5. 4 Bifase
Prima segniamo la chiave obsoleta (soft TTL), manteniamo stale, aggiorniamo e sostituiamo atomicamente lo sfondo.
6) Lotta con stampede/dogpile e chiavi calde
6. 1 Request coalescing (singleflight)
Un produttore aggiorna la chiave, gli altri attendono il risultato (l'etichetta è aggiornata).
6. 2 Jitter к TTL
Aggiungi la casualità (© 10-20%) alla TTL per evitare la perforazione sincrona.
6. 3 Soft-TTL + hard-TTL
Prima del servizio soft-TTL dalla cache, parallelamente al trigger refresh; per hard-TTL - riteniamo un errore.
6. 4 Chiavi calde
Cache locale sopra quelle comuni (two-tier).
Replica della chiave calda in più chard e selezione random (solo read-only).
Rate limit per l'aggiornamento di una chiave specifica.
6. 5 Esempio Redis + Lua (singleflight-sketch)
lua
-- SETNX lock with TTL to avoid deadlocks local ok = redis. call("SET", KEYS[1], "1", "NX", "EX", ARGV[1])
if ok then return "LOCKED"
else return "WAIT"
end
7) Criteri di espulsione e accettazione della cache
7. 1 Eviction
LRU è semplice e buono per la località.
LFU: Meglio con chiavi hot a lunga vita.
ARC/TinyLFU - equilibrio recency/frequency.
7. 2 Admision (inserimento)
Non immettere oggetti rari giganti (TinyLFU/Blom-Filtri).
Compressione di grandi valori (LZ4/Zstd) al limite di quota/latenza.
8) Scharding e topologia
8. 1 Consistent hashing
Distribuisce stabilmente le chiavi sui nodi, riducendo i movimenti durante la crescita o la compressione del cluster.
8. 2 Topologie Redis/Memcached
Redis Cluster (slot/chard), Sentinel (feelover), replica read-only.
Memcached è un client-side sharding (ketama hasing) senza replica a livello di server.
8. 3 Locale + distribuito
Cascata: in-proc (micro-TTL/LRU) Redis (TTL) più lunga della sorgente.
Attenzione ai due punti TTL e ai validatori cache.
9) Edge, CDN e L7-cash
9. 1 Micro-cache на Nginx
nginx proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api:100m inactive=10m;
map $request_method $skip_cache { default 0; POST 1; PUT 1; DELETE 1; }
server {
location /api/list {
if ($skip_cache) { add_header Cache-Control "no-store"; }
proxy_cache api;
proxy_cache_valid 200 2s; # micro-cache proxy_cache_use_stale error timeout updating;
proxy_cache_background_update on; # SWR add_header X-Cache $upstream_cache_status;
proxy_pass http://upstream;
}
}
9. 2 Avvoy (SWR e condizioni)
yaml http_filters:
- name: envoy. filters. http. cache typed_config:
"@type": type. googleapis. com/envoy. extensions. filters. http. cache. v3. CacheConfig typed_config:
"@type": type. googleapis. com/envoy. extensions. http. cache. file_system_http_cache. v3. FileSystemHttpCacheConfig cache_path: "/var/cache/envoy"
9. 3 Varnish (Surrogate keys)
Usa i tag Surrogate-Key e Ban per la disabilità batch.
10) Kash e coerenza dei dati
10. 1 Read-your-writes
Per i profili/cestini personalizzati, fornire TTL brevi o scrivere nella cache (write-through) o contrassegnare il client (bypass per N secondi dopo la scrittura).
10. 2 Eventual vs Strong
Per raccomandazioni/analisi - eventual + TTL lunga.
Per denaro/stato degli ordini - TTL breve, convalida, a volte senza cache su percorsi critici.
10. 3 Invarianti
Non memorizzare i campi che influiscono sulla protezione/ACL senza TTL rigorosi e senza riesaminazione.
11) Osservazione, SLO e controllo
11. 1 Metriche
hit_ratio (общий и per-route), byte_hit_ratio, miss_rate.
stampede_prevented_total, refresh_ahead_total, ban/purge_total.
Latenza: p50/p95/p99 dalla cache vs dall'origine.
hot_keys_topN i loro QPS/byte.
11. 2 Logi e tracciati
Logica «X-Cache: HIT/MISS/STALE/UPDATING».
Nei trailer, segnare l'origine della risposta («cache = true», «tier = edge» service «locale»).
11. Approccio SLO 3
Esempio: "per API/catalog p99 250 mc, cache hit 85%, stampede 0. 1% di richieste".
11. 4 Runbooks
Gli errori crescono per controllare TTL, riscaldamento/invalidità, hot-keys, dimensioni della cache e criteri di accettazione.
12) Sicurezza e multi-tenenza
Incorporare il tenant-id nelle chiavi (e in «Vary» con HTTP).
Non lasciare che le risposte private siano «public».
Crittografare la cache con dati sensibili o memorizzare solo i dati non PII/ID.
13) Ricette tipiche
13. 1 Catalogo/nastro (quasi altoparlante)
Edge-Microcesh 1-3 con + SWR, dentro - Redis a 15-60 s, disabilità per eventi di aggiornamento.
13. 2 Profilo utente
Cache-aside con TTL 30-120 s, bypass 5-10 s dopo l'aggiornamento del profilo (cookie/heder), o write-through.
13. 3 Valuta-corsi/manuali
TTL lunghi (minuti-orari) + disabilità target durante la pubblicazione di nuovi dati; «ETAG» per GET condizionati.
13. 4 Rilascio di ricerca
Edge-Microcesh 1-2 con, all'interno - refresh-ahead e coalescing, normalizzazione dei parametri query in chiave.
14) Anti-pattern
La cache è priva di invalidità. La speranza di una TTL è di lunga durata.
Il gigantesco «Vary», «esplosione» delle opzioni, è un hit-rate basso.
Un'unica cache per i prod/experimenti per l'inquinamento.
Nessuna protezione da stampede all'origine al termine della TTL.
Cache di denaro/diritti/ACL senza garanzie severe.
La compressione «solo di fila» è una CPU in eccesso, un peggioramento del p99 nei piccoli impianti.
15) Assegno-foglio di implementazione
- Definire i livelli di cache e i relativi obiettivi (edge/service/locale).
- Progettare le chiavi (versioning, tenant, normalizzazione dei parametri).
- Selezionare il pattern (cache-aside/read-through/refresh-ahead).
- Configurare TTL/soft-TTL/jitter, attivare SWR.
- Implementare coalescing/singleflight, protezione contro stampede.
- Organizzare la disabilità (eventi, tag, purge/ban).
- Immettere le metriche hit-ratio/latitanza e dashboard X-Cache.
- Eseguire test di carico con chiavi hot.
- Inserire SLO e runbooks.
- Controllare la sicurezza/tenant-isolamento e «Vary».
16) FAQ
Q: Cosa scegliere: cache-aside o read-through?
A: Per i servizi semplici - cache-aside. Serve centralizzazione e un'unica politica - read-through.
Q: Come si capisce la TTL migliore?
A: Allontanarsi dall'obsolescenza, dalla frequenza degli aggiornamenti e dall'hit-rate di destinazione aggiungere jitter e osservare p95/p99/costo.
Q: Quando è appropriato write-back?
A: Per i flussi ad alta velocità, dove la consistenza eventual è accettabile e c'è una coda/login affidabile per «finitura».
Q: È possibile memorizzare le risposte autorizzate?
A: Sì, ma segnare «private» e/o includere tenant/user nella chiave/« Vary ». Per truly-private è la cache client.
Come si scalda la cache?
A: Elenchi di chiavi popolari, background wormer, replay da tana, riscaldamento prima del rilascio/pick (Black Friday, ecc.).
17) Riepilogo
Cache efficiente è il design delle chiavi + TTL intelligenti + il pattern scelto correttamente, rafforzato da disabilità per eventi, SWR/refresh-ahead e protezione contro stampede. Espandere la cache in base ai livelli (client/edge/servizio), aggiungere osservabilità e SLO e ottenere code di latenza stabili, costi prevedibili e resistenza ai picchi di carico.