Data Caching
PerformanceTeknik til at gemme ofte-brugt data i hurtig storage for at reducere latency og database load.
Beskrivelse
Caching er praksis hvor frequently accessed data gemmes i et hurtigt lag (typisk in-memory) så fremtidige requests kan serveres meget hurtigere. I stedet for at query databasen hver gang, checker man først cache - hvis data findes (cache hit), returneres det direkte. Hvis ikke (cache miss), hentes data fra database og gemmes i cache til næste gang. Populære caching strategier inkluderer: Cache-Aside (application checker cache først), Write-Through (skriv til både cache og DB), Write-Behind (skriv til cache, DB asynkront), og Read-Through (cache selv henter fra DB). Common caching teknologier er Redis og Memcached. Vigtige overvejelser inkluderer cache eviction policies (LRU, LFU, FIFO), TTL (Time To Live), og cache invalidation (det svære problem). Korrekt caching kan reducere latency fra 100ms til under 1ms og reducere database load med 90%+.
Problem
Database queries kan være langsomme - disk I/O, komplekse joins, aggregations. Når tusinder af brugere requester samme data (f.eks. produktkatalog, artikler), bombarderer de databasen med identiske queries. Dette spildes resources og giver dårlig performance.
Løsning
Cache frequently accessed data i RAM. Første request henter fra database og gemmer i cache. Næste 1000 requests serveres direkte fra cache med sub-millisecond latency. Database load reduceres drastisk.
Eksempel
// Cache-Aside Pattern (Lazy Loading)
class ProductService {
constructor(db, cache) {
this.db = db;
this.cache = cache; // Redis client
}
async getProduct(productId) {
const cacheKey = `product:${productId}`;
// 1. Check cache først
let product = await this.cache.get(cacheKey);
if (product) {
console.log('Cache HIT');
return JSON.parse(product);
}
// 2. Cache MISS - hent fra database
console.log('Cache MISS - querying database');
product = await this.db.query(
'SELECT * FROM products WHERE id = $1',
[productId]
);
// 3. Gem i cache med TTL (1 time)
await this.cache.setex(
cacheKey,
3600, // TTL i sekunder
JSON.stringify(product)
);
return product;
}
async updateProduct(productId, data) {
// Update database
await this.db.query(
'UPDATE products SET name=$1, price=$2 WHERE id=$3',
[data.name, data.price, productId]
);
// Cache Invalidation - fjern cached version
await this.cache.del(`product:${productId}`);
// Næste read vil cache miss og hente fresh data
}
}
-----------------------------------------------------
// Write-Through Cache
async function saveUser(userId, userData) {
// Skriv til BÅDE database OG cache
await Promise.all([
db.query('INSERT INTO users VALUES ($1, $2)', [userId, userData]),
cache.set(`user:${userId}`, JSON.stringify(userData))
]);
// Cache er altid synchronized med database
}
-----------------------------------------------------
// Cache with TTL and Layers
class CacheService {
async getPopularProducts() {
const cacheKey = 'products:popular';
// L1: In-memory cache (meget hurtig)
if (this.memoryCache.has(cacheKey)) {
return this.memoryCache.get(cacheKey);
}
// L2: Redis cache
const redisData = await redis.get(cacheKey);
if (redisData) {
this.memoryCache.set(cacheKey, JSON.parse(redisData));
return JSON.parse(redisData);
}
// L3: Database (slowest)
const dbData = await db.query(`
SELECT * FROM products
ORDER BY sales_count DESC
LIMIT 20
`);
// Cache i begge layers
await redis.setex(cacheKey, 300, JSON.stringify(dbData));
this.memoryCache.set(cacheKey, dbData);
return dbData;
}
}Fordele
- ✓Drastisk reduceret latency (100ms → 1ms)
- ✓Reduceret database load (90%+ reduction)
- ✓Bedre skalering af read-heavy workloads
- ✓Lavere hosting costs (mindre DB resources)
- ✓Forbedret user experience
Udfordringer
- ⚠Cache invalidation er svært ('hardest problem')
- ⚠Stale data hvis ikke invalideret korrekt
- ⚠Extra complexity og moving parts
- ⚠Memory costs for cache layer
- ⚠Cold cache performance (efter restart)
Anvendelsesområder
- •Homepage content og navigation
- •Produktkataloger i e-commerce
- •User sessions og authentication tokens
- •API rate limiting counters
- •Computed/aggregated data
Eksempler fra den virkelige verden
- •Facebook feed: Cache posts for millioner af users
- •Netflix: Cache movie metadata og thumbnails
- •Amazon: Cache produktdetaljer og priser
- •Wikipedia: Cache artikler (læses meget oftere end opdateres)
- •News sites: Cache artikler med TTL på 5 minutter