Uçta Kalıcılık: Workers KV, R2 Object Storage ve D1 SQLite
Cloudflare Workers'ta bulunan üç depolama katmanı arasındaki pratik karşılaştırma: Küresel anahtar/değer verileri için KV, çıkış ücreti olmadan nesne depolama için R2 ve D1 uçtaki ilişkisel SQL sorguları için.
Sınırda Kalıcılık Sorunu
V8, Cloudflare Çalışanlarının tasarım gereği vatansız oldukları gücünü izole eder: her biri izole edilmiştir mikrosaniyeler içinde oluşturulabilir ve yok edilebilir, ancak yerel JavaScript durumu istekler arasında devam ediyor (veya aynı anda eşzamanlılık nedeniyle yalnızca ara sıra devam ediyor) izole edilmiştir). Gerçek uygulamalar oluşturmak için harici kalıcılığa ihtiyacınız vardır.
Cloudflare, her biri bir kullanım senaryosu için tasarlanmış üç yerel depolama ürünü sunar spesifik. Yanlış olanı seçmek yavaş sorgular ve yüksek maliyetler anlamına gelebilir veya hata ayıklaması zor tutarsızlıklar. Bu makale bunları ayrıntılı olarak karşılaştırmaktadır. Gerçek kod örnekleri.
Ne Öğreneceksiniz
- Workers KV: sonuçta tutarlı mimari, API, sınırlar ve ideal kullanım örnekleri
- Cloudflare R2: Çıkış ücreti olmadan S3 uyumlu nesne depolama, çok parçalı yükleme
- D1 SQLite: uçta ilişkisel veritabanı, SQL sorguları, Drizzle ORM ile geçişler
- Maliyet karşılaştırması: Farklı kullanım ölçeklerinde KV, R2 ve D1
- Entegrasyon Modeli: Akıllı önbelleğe alma için KV + D1 nasıl birleştirilir?
- Her depolama türü için wrangler.toml'deki bağlamaları yapılandırma
Workers KV: Küresel Anahtar-Değer ve Sonunda Tutarlı
Workers KV, küresel olarak dağıtılmış bir anahtar/değer veri deposudur. Yazdığında bir değer, saniyeler içinde tüm Cloudflare PoP'larında çoğaltılır. Okuduğunuzda, en yakın PoP'tan değer elde edin: okuma gecikmesi genellikle 1 ms'den azdır.
Temel değiş-tokuş: KV sonuçta tutarlı. Bir yazı küresel olarak görünür hale gelmesi 60 saniye kadar sürebilir. Bu onu yapar sık değişen ve hemen okunması gereken veriler için uygun değildir yazdıktan sonra.
wrangler.toml'de KV yapılandırması
# wrangler.toml
[[kv_namespaces]]
binding = "CACHE" # Nome del binding nel codice TypeScript
id = "xxxxxxxxxxxxxxxxxx" # ID del namespace in produzione
preview_id = "yyyyyyyyyy" # ID del namespace per wrangler dev
[[kv_namespaces]]
binding = "SESSIONS"
id = "aaaaaaaaaaaaaaaaa"
preview_id = "bbbbbbbbbbbbb"
# Per creare i namespace:
# wrangler kv namespace create CACHE
# wrangler kv namespace create CACHE --preview
TypeScript'te Workers KV API'si
// src/services/cache.service.ts
export interface Env {
CACHE: KVNamespace;
SESSIONS: KVNamespace;
}
// -------- OPERAZIONI BASE --------
// WRITE: put con TTL opzionale (in secondi)
await env.CACHE.put('user:123', JSON.stringify({ name: 'Mario', role: 'admin' }), {
expirationTtl: 3600, // scade tra 1 ora
});
// WRITE senza TTL (valore permanente)
await env.CACHE.put('config:features', JSON.stringify({ darkMode: true }));
// WRITE con expiration assoluta (Unix timestamp)
await env.CACHE.put('promo:summer', 'active', {
expiration: Math.floor(Date.now() / 1000) + 86400, // scade tra 24h
});
// READ: get con tipo di decodifica
const raw = await env.CACHE.get('user:123');
// raw: string | null
const parsed = await env.CACHE.get<{ name: string; role: string }>('user:123', 'json');
// parsed: { name: string; role: string } | null
// READ con metadata
const { value, metadata } = await env.CACHE.getWithMetadata('user:123', 'json');
// DELETE
await env.CACHE.delete('user:123');
// -------- LISTING (con limitazioni) --------
// KV supporta listing, ma e lento e con limite di 1000 chiavi per chiamata
const listing = await env.CACHE.list({ prefix: 'user:', limit: 100 });
for (const key of listing.keys) {
console.log(key.name, key.expiration, key.metadata);
}
// -------- PATTERN: cache-aside --------
async function getUserCached(userId: string, env: Env): Promise<User | null> {
const cacheKey = `user:${userId}`;
// 1. Controlla la cache KV
const cached = await env.CACHE.get<User>(cacheKey, 'json');
if (cached) {
return cached; // Cache hit: risposta da KV < 1ms
}
// 2. Cache miss: fetch dall'origine
const user = await fetchUserFromDatabase(userId);
if (!user) return null;
// 3. Popola la cache (eventually consistent, ok per profili utente)
await env.CACHE.put(cacheKey, JSON.stringify(user), {
expirationTtl: 300, // 5 minuti
});
return user;
}
| karakteristik | KV detayı |
|---|---|
| Tutarlılık modeli | Sonunda tutarlı (maksimum 60 saniye yayılma) |
| Gecikmeyi okuma | < 1 ms (ısınma sonrasında yerel PoP'tan) |
| Gecikme yazma | ~100 ms (onay), eşzamansız küresel çoğaltma |
| Maksimum değer boyutu | Değer başına 25MB |
| Maksimum anahtar boyutu | 512 bayt |
| Okuma maliyeti | Milyon başına 0,50 ABD doları (ücretsiz: 10 milyon/ay) |
| Yazma maliyeti | Milyon başına 5 ABD doları (ücretsiz: 1 milyon/ay) |
| Şunun için idealdir: | Yapılandırma, özellik işaretleri, oturum deposu, API önbelleğe alma |
| için uygun değil | Gerçek zamanlı sayaçlar, her saniye değişen veriler |
Cloudflare R2: Çıkış Ücreti Olmayan S3 Uyumlu Nesne Depolama
R2, 2022 lansmanında en çok ses getiren ürün oldu: nesne depolama AWS S3 API'leriyle uyumlu, sıfır çıkış maliyeti. S3'te, 1 TB veriyi internete aktarmanın maliyeti ~90







