Le tre primitive di archiviazione di Cloudflare - KV, R2 e Cache API - compaiono insieme nella documentazione e condividono lo stesso runtime, il che crea l'impressione che siano alternative allo stesso problema. Non lo sono. Ciascuno è stato costruito con un'architettura diversa, per un carico di lavoro diverso, con un modello di costo diverso. Usare quello sbagliato non solo è inefficiente: in alcuni casi semplicemente non funziona.
La confusione è comprensibile. Tutti e tre i "dati di archiviazione". Ma la distinzione rilevante non è ciò che fanno in astratto: riguarda il modo in cui ciascuno di essi si comporta nel traffico reale, quanto costa su larga scala e quali garanzie offrono.
KV: l'archivio globale per dati piccoli e letti frequentemente
KV è un negozio di valori-chiave distribuito a livello globale. Le scritture vengono inviate a un archivio centrale e si propagano a più di 300 PoP in un massimo di 60 secondi. Le letture arrivano in meno di un millisecondo se la chiave è memorizzata nella cache nel PoP più vicino o in ~20 ms se deve essere recuperata dall'archivio centrale.
Il modello di costo favorisce le letture a volume: 0,50 dollari per milione di letture dopo i primi 10 milioni di letture mensili gratuite. Le scritture costano gli stessi $ 0,50 per milione, ma con solo 1 milione gratuito. Il limite massimo per valore è 25 MB.
KV funziona bene per dati scritti raramente e letti in modo massiccio: configurazione del prodotto, feature flag, modelli, indici di contenuto, token di sessione con TTL. Funziona male per tutto ciò che cambia frequentemente o richiede coerenza immediata: l'eventuale coerenza con una finestra fino a 60 secondi e l'assenza di operazioni atomiche sono limitazioni reali, non dettagli della documentazione.
R2: archiviazione di oggetti senza tariffa di uscita
R2 è l'object storage di Cloudflare, equivalente funzionale a S3. È stato creato per file di grandi dimensioni: immagini, video, backup, esportazioni di dati, risorse statiche. La differenza competitiva rispetto a S3 è l’assenza di una tariffa in uscita: non si paga per trasferire i dati da R2 a internet, che in S3 è una delle linee più penose della bolletta.
Il costo di archiviazione è di $ 0,015/GB al mese. Ogni operazione di lettura (GET) in R2 conta come una richiesta: non esiste una cache automatica globale come in KV. Se OTTIENI un oggetto R2 in ciascuna richiesta Worker, stai pagando per ciascuna richiesta più il tempo di latenza di ciascun GET. Ciò rende R2 inadatto per dati ad alta frequenza di lettura per richiesta.
La combinazione corretta consiste nell'utilizzare R2 per il file e KV (o l'API Cache) per l'indice o la versione memorizzata nella cache. Un lavoratore che fornisce immagini può archiviare il file binario in R2 e mantenere un JSON in KV con URL firmati, metadati e intestazioni HTTP: quindi la lettura frequente accede a KV in meno di millisecondi e R2 viene toccato solo per i caricamenti e la generazione di URL.
Il limite per oggetto in R2 non è lo stesso di KV: sono supportati più file GB. Per KV con un massimo di 25 MB per valore, R2 è la destinazione naturale per tutti i dati che superano questa soglia.
Cache API: la cache di risposta HTTP per PoP
L'API Cache memorizza Response oggetti nella cache HTTP del PoP corrente. È gratuito, senza quote operative e funziona come un livello di memorizzazione nella cache sulle risposte HTTP, non come un archivio di stati condivisi.
Il dettaglio critico che lo differenzia da KV è l'ambito: l'API Cache è per PoP, non globale. Un colpo alla cache nel PoP di San Paolo non influenza il PoP di Francoforte. Se un lavoratore a Francoforte non ha mai ricevuto una richiesta per quell'URL, la cache sarà fredda a Francoforte, indipendentemente da quante volte San Paolo ha fornito quella risposta dalla cache.
Un altro limite: il contenuto dell'API Cache può essere eliminato dal PoP in qualsiasi momento a causa della pressione dell'LRU. Non esiste alcuna garanzia di persistenza tra le richieste: la richiesta successiva per la stessa risorsa potrebbe incontrare la cache fredda, anche se la richiesta precedente l'ha popolata.
L'API Cache funziona bene per deduplicare le richieste alle API di terze parti in un breve periodo di tempo: la recuperi una volta, la metti nella cache Response per 30 secondi e le richieste successive nello stesso PoP riutilizzano la risposta senza chiamare l'API upstream. Serve anche per memorizzare nella cache le risposte computazionalmente costose richieste in burst nello stesso PoP.
Cosa non funziona: utilizzare l'API Cache come stato condiviso tra Worker o tra regioni. Due istanze Worker in PoP diversi non vedranno lo stesso stato della cache. Per lo stato condiviso, KV è la soluzione.
La matrice anti-pattern
Usare R2 per la configurazione dell'applicazione è l'errore più comune tra i team che arrivano da S3. Su S3, è normale archiviare config.json in un bucket e leggerlo all'avvio dell'applicazione: il server dura ore o giorni, quindi un GET a ogni riavvio è economico. In Lavoratori, ogni isolato può essere creato e distrutto frequentemente. Ogni GET to R2 ha la latenza di una richiesta di rete e conta come un'operazione addebitata. Per la configurazione, KV con memorizzazione nella cache a livello di modulo è il modello corretto.
L'uso di KV per file video o set di dati di grandi dimensioni è l'altro estremo. Il limite di 25 MB per valore crea già problemi immediati per qualsiasi risorsa di dimensioni reali. Ma oltre questo limite, il costo di scrittura su KV è proibitivo per i file che arrivano frequentemente tramite caricamento utente. R2 a $ 0,015/GB al mese è molto più economico per l'archiviazione di file di grandi dimensioni.
L'utilizzo dell'API Cache per qualsiasi tipo di stato che deve essere coerente tra i PoP è una fonte garantita di comportamento irregolare. Il sintomo tipico è un bug che appare "a volte" — perché il PoP che ha servito la richiesta precedente aveva la cache popolata, mentre il PoP che ha servito questa no. L'API cache non sostituisce KV per i dati globali.
##Come scegliere
La decisione inizia con il tipo di dati e la frequenza di accesso. Piccoli dati, letti molte volte al secondo, necessitano di una distribuzione globale: KV. File di grandi dimensioni, scritto tramite caricamento e letto con frequenza da bassa a moderata: R2. Risposta HTTP che cambia raramente e potrebbe essere locale al PoP: API Cache.
Il costo conferma o scarta la scelta. Se il volume delle scritture è elevato, KV diventa costoso. Se il volume dei singoli GET per file è elevato, R2 diventa costoso e lento. Se hai bisogno di coerenza tra PoP, l'API Cache non va bene.
Combinare i tre è il modello corretto
Il modello che appare più spesso nelle architetture mature con Workers è la combinazione deliberata. R2 memorizza il binario. KV memorizza l'indice, i metadati e l'URL firmato di breve durata. L'API cache deduplica le richieste burst sullo stesso PoP. Ogni livello fa ciò per cui è stato progettato e il risultato è uno stack di storage che funziona bene e costa quello che dovrebbe costare.
La trappola sta cercando di semplificare in un'unica primitiva. Cloudflare li offre tutti e tre perché ognuno risolve un problema diverso. Comprendere il confine tra loro è ciò che separa un'implementazione che funziona in fase di sviluppo da una che sopravvive al traffico reale.
Leggi anche
- Cloudflare KV: cosa significa distribuzione globale quando è necessario scrivere
- Invalidazione della cache in KV: il problema che nessuno risolve elegantemente
- Bilanciamento del carico e geodirezione di Cloudflare: quando il DNS diventa un livello di traffico intelligente
- KV nella produzione: gli schemi che funzionano e quelli che traggono in inganno all'inizio
- [KV per limitazione della velocità, flag di funzionalità e configurazione distribuita: dove funziona e dove si interrompe7
- Lavoratori + D1 + KV + R2: comporre associazioni nello stesso servizio
