7.7 Cache-elés alapjai

← 7. Systems thinking – A nagy kép

7.7 Cache-elés alapjai – mikor gyorsít, mikor okoz fejfájást

Áttekintő

A cache-elés az egyik leghasznosabb – és egyben legtöbb félreértést okozó – technika a szoftverfejlesztésben. Ha jól alkalmazzák, drasztikusan gyorsítja az alkalmazásokat. Ha rosszul, a felhasználók régi adatot látnak, a fejlesztők órákat töltnek a hibakeresésssel, és senki nem érti, mi történik.

Ez az alfejezet nem arról szól, hogyan implementálj cache-t nulláról. Arról szól, hogyan gondolkodj cache-ről fejlesztőként: mikor segít, mikor árt, és hogyan ismerd fel, ha a cache az, ami problémát okoz.

Miért számít az állásinterjún?
„A fejlesztő módosított valamit, de az oldalon még a régi tartalom látszik" – ezt a szituációt szinte minden junior fejlesztő megéli az első hónapokban. Ha tudod, miért történik és hol kell keresni a megoldást, azonnal kitűnsz a mezőnyből.

Miért számít production-ban?
Cache-hibák az egyik legnehezebben debuggolható osztályba tartoznak, mert a kód helyes, a logika helyes – csak épp nem azt az adatot mutatja, amit várnál.


Részletes leírás

Mi a cache és miért hasznos?

A cache (ejtsd: „kesh") egy ideiglenes tároló, ahol megőrizzük egy korábban elvégzett számítás vagy lekérdezés eredményét – azzal a céllal, hogy legközelebb ne kelljen újra elvégezni.

Az alaplogika mindig ugyanaz:

Van már a cache-ben eredmény erre a kérésre?
  → IGEN: visszaadjuk onnan (gyors)
  → NEM: elvégezzük a munkát, eltároljuk a cache-ben, visszaadjuk (lassú, de csak egyszer)

Miért gyorsít?

Mert az eredeti művelet drága: adatbázis-lekérdezés, API-hívás, komplex számítás, fájl beolvasása. Ha ezt ezer felhasználó kéri, ezer drága műveletet kellene elvégezni. Cache-szel: egyszer elvégezzük, ezer felhasználó megkapja az eltárolt eredményt.


A cache szintek – hol találkozhatsz vele fejlesztőként?

Cache nem csak egy helyen létezik. Több réteg is cache-elhet egyszerre – és ez az, ami megnehezíti a hibakeresést.

1. Böngésző cache

A böngésző eltárolja a letöltött fájlokat (CSS, JS, képek, HTML) – hogy ne kelljen minden oldalbetöltésnél újra letölteni.

Ezt a szerver irányítja HTTP fejlécekkel:

Cache-Control: max-age=3600    # 1 óráig cache-elhető
Cache-Control: no-cache        # mindig kérd le újra
ETag: "abc123"                 # verzió azonosító

Fejlesztőként: Ha módosítottál egy CSS fájlt és nem látod a változást, lehetséges, hogy a böngésző a régi, cache-elt verziót mutatja. Ctrl+Shift+R (hard refresh) megoldja.

2. CDN (Content Delivery Network) cache

A CDN egy globálisan elosztott szerverhálózat, amely közelebb viszi a statikus tartalmakat (képek, videók, JS/CSS fájlok) a felhasználókhoz.

A CDN is cache-eli ezeket a tartalmakat – és ez saját élete szerint frissül, nem azonnal, amikor te push-olsz.

Fejlesztőként: „Miért látja már a változást az USA-ban, de Európában még a régi van?" – CDN cache invalidáció különböző régiókban különböző sebességgel zajlik.

3. Szerver oldali cache (alkalmazás szintű)

Az alkalmazás saját maga cache-el memóriában vagy egy külső cache tárban (Redis, Memcached):

# Python példa - Redis-szel
def get_user_profile(user_id):
    cache_key = f"user:{user_id}:profile"
    
    cached = redis.get(cache_key)
    if cached:
        return json.loads(cached)  # cache találat
    
    # cache miss - adatbázisból lekérjük
    profile = db.query("SELECT * FROM users WHERE id = ?", user_id)
    redis.setex(cache_key, 3600, json.dumps(profile))  # 1 órára cache-eljük
    return profile
// JavaScript példa - egyszerű in-memory cache
const cache = new Map();

async function getProductDetails(productId) {
    if (cache.has(productId)) {
        return cache.get(productId); // cache találat
    }
    
    const product = await db.findById(productId);
    cache.set(productId, product);
    return product;
}

Fejlesztőként: Ha egy felhasználó megváltozott profiljára a régi adatot látod visszajönni az API-ból, valószínűleg a szerver oldali cache nem invalidálódott.

4. Adatbázis cache

Az adatbázisok is cache-elnek belülül – query cache, buffer pool, connection cache. Ezt általában nem a fejlesztő konfigurál közvetlenül, de tudatában kell lenni a létezéséről.


Cache invalidáció – a legnehezebb probléma

„A számítástechnikában két nehéz dolog van: cache invalidáció és az elnevezések."
— Phil Karlton

Cache invalidáció azt jelenti: mikor és hogyan töröljük a cache-ből az elavult adatot.

Ez azért nehéz, mert bármikor módosulhat az eredeti adat – és a cache erről nem tud automatikusan. Három fő stratégia létezik:

1. TTL (Time To Live) – lejárati idő

A legegyszerűbb megközelítés: a cache-elt adat X idő után automatikusan törlődik.

// PHP példa - Laravel cache-szel
$userData = Cache::remember("user:{$userId}", 3600, function() use ($userId) {
    return User::find($userId);
});
// 3600 másodperc (1 óra) után a cache automatikusan invalidálódik

Trade-off: Egyszerű, de nem frissül azonnal. Ha egy felhasználó megváltoztatja a nevét, max 1 óráig a régi nevet láthatja valaki más.

2. Aktív invalidáció – törlés változáskor

Amikor az adat megváltozik, explicit törljük a cache-ből:

def update_user_profile(user_id, new_data):
    db.update("UPDATE users SET ... WHERE id = ?", user_id, new_data)
    redis.delete(f"user:{user_id}:profile")  # cache törlése változáskor

Trade-off: Pontosabb, de bonyolultabb – minden módosítási helyen emlékezni kell a cache törlésére. Ha egy helyen elfelejtjük, stale data keletkezik.

3. Cache-aside (lazy loading)

Csak akkor töltjük be a cache-be, amikor valaki kéri. Lejárat után is csak akkor frissül, ha valaki újra kéri.


Stale data – az elavult adat problémája

Stale data (elavult adat) akkor keletkezik, amikor a cache-ben lévő adat már nem egyezik az eredeti forrással.

Tipikus esetek junior fejlesztőknek:

SzituációMiért történik
Admin módosít valamit, de a felhasználók még a régit látjákSzerver cache nem invalidálódott
Fejlesztő deploy-olt, de a böngésző régi JS-t töltBöngésző cache-ből tölti, nem a szerverről
API helyes adatot ad, de a frontend rossz adatot mutatKliens oldali cache (SWR, React Query, stb.)
Kép frissítve lett, de régi kép jelenik megCDN cache még a régit mutatja

Mikor NE cache-elj?

Nem minden adat alkalmas cache-elésre. Kerüld a cache-t, ha:

  1. Az adat sűrűn változik – Ha percenként frissül, a cache csak gondot okoz
  2. Az adat felhasználóspecifikus és érzékeny – Véletlenül más felhasználó cache-ét visszaadni adatvédelmi katasztrófa
  3. Az adat valós idejű pontossága kritikus – Pénzügyi tranzakciók, készletinformáció
  4. A számítás annyira gyors, hogy a cache overhead nagyobb – Cache is költség

Mikor gyanakodj cache-re fejlesztőként?

Ha ezeket a tüneteket tapasztalod, cache lehet az ok:

  • Valaminek frissülnie kellett volna, de nem frissült – Módosítottál valamit, de nem látszik
  • Különböző felhasználók különböző adatot látnak – Valakinek cache találat, másnak nem
  • Hard refresh (Ctrl+Shift+R) megoldja a problémát – Böngésző cache volt
  • Inkognitó módban más eredményt kapsz – Böngésző cache van
  • Staging-en helyes, production-on régi adat – CDN vagy szerver cache különbség
  • Néhány perccel/órával később „magától megjavul" – TTL lejárt, friss adat jött

Életszerű példák

1. példa: „Miért nem látja a felhasználó az új árát?"

Webshopban frissítettétek egy termék árát az admin felületen. Az admin oldalon már az új ár látszik. De az ügyfelek még a régit látják.

Mi történt?
A termék detail oldala 30 percre van cache-elve (CDN vagy szerver cache). Az admin módosított, de a cache nem invalidálódott.

Hogyan javítottátok:
Az ár módosításakor aktív cache invalidációt kellett volna triggerelni. Vagy rövidebb TTL-t beállítani ennél az endpointnál.


2. példa: „A kép frissült, de a régi jelenik meg"

Frissítettetek egy banner képet a weboldalon. Lokálisan tökéletes. Production-ban még a régi kép látszik.

Mi történt?
A kép ugyanolyan névvel lett feltöltve (banner.jpg). A CDN cache-eli a régi banner.jpg-t, és nem tudja, hogy a fájl tartalma megváltozott.

Hogyan védd meg magad:
Cache busting technika: a fájlnévbe version hash kerül (banner.a3f8b2.jpg). Ha a tartalom változik, a fájlnév is változik, a CDN kénytelen újra letölteni.


3. példa: „Tesztelés közben furcsa adatot kaptam"

Fejlesztés közben módosítottál egy rekordot az adatbázisban közvetlenül (SQL-lel). De az API még a régi adatot adja vissza.

Mi történt?
Az alkalmazás cache-eli az adott rekordot (pl. Redis-ben). Közvetlen adatbázis módosítás nem triggereli a cache invalidációt.

Tanulság:
Fejlesztésben gyanakodj a szerver cache-re, ha az adatbázisban mást látsz, mint amit az API visszaad. Redis flush (helyi fejlesztői környezetben) megoldhatja.


4. példa: A cache mint jó eszköz – mikor valóban segít

Képzeld el: van egy endpoint, ami összeszámolja a weboldalon lévő összes terméket kategóriánként. Ez egy komplex lekérdezés, 500ms-ba telik. 1000 felhasználó percenként kéri.

Cache nélkül: 1000 × 500ms adatbázis terhelés percenként.
Cache-sel (5 perces TTL): 1 lekérdezés 5 percenként, 999 kérés cache-ből.

Ez az, ahol a cache valóban számít.


Feladatok

Gyakorlati feladat

Szituáció: Régi adat jelenik meg – hol a cache probléma?

Te vagy az új junior fejlesztő egy e-commerce cégben. A product manager jelezte: egy felhasználó 2 napja megváltoztatta a szállítási címét a profiljában, de a rendeléseknél még a régi cím jelenik meg.

Elemzési feladat: Sorold fel a lehetséges cache szinteket, ahol a probléma előfordulhat, és adj meg egy-egy ellenőrzési lépést mindegyikhez.

Cache szintHogyan ellenőrizném?
Böngésző cache...
Szerver oldali cache...
CDN...

(Saját gondolataiddal töltsd ki – nincs egyetlen helyes válasz, de minden szintnek van releváns ellenőrzési módja.)


Tesztfeladatok

1. Mi a cache alapvető célja?

a) Biztonsági mentés készítése az adatokról
b) Drága műveletek eredményének ideiglenes tárolása a gyorsabb visszaadáshoz
c) Az adatbázis helyettesítése
d) A felhasználói munkamenet tárolása

(Helyes: b)


2. Egy fejlesztő módosított egy CSS fájlt és feltöltötte a szerverre. Az oldalon még a régi stílus látszik. Mi az első dolog, amit kipróbálna?

a) Újratelepíti az alkalmazást
b) Megkéri a felhasználót, hogy törölje a sütijeit
c) Hard refresh (Ctrl+Shift+R) a böngészőben
d) Újraindítja az adatbázist

(Helyes: c)


3. Mi a „cache invalidáció" fogalma?

a) A cache törlése a szerver leállításakor
b) A cache-elt adat frissítése vagy törlése, ha az eredeti adat megváltozott
c) A cache méretének növelése
d) A cache biztonsági beállítása

(Helyes: b)


4. Melyik szituációban NEM érdemes cache-t használni?

a) Statikus weboldalak képeinél
b) Lassan változó terméklistáknál
c) Valós idejű tőzsdei árfolyamoknál
d) Publikus blog bejegyzéseknél

(Helyes: c)


5. Mi a „stale data" fogalma cache kontextusban?

a) Törölt adatok a cache-ből
b) Cache-ben tárolt adat, ami már nem egyezik az eredeti forrással
c) Titkosított cache tartalom
d) Lejárt session adatok

(Helyes: b)


6. Mit jelent a TTL (Time To Live) a cache-elésnél?

a) A szerver maximális válaszideje
b) Az az időtartam, ameddig a cache-elt adat érvényes
c) A cache maximális mérete
d) A kapcsolat időkorlátja

(Helyes: b)


7. Egy webshopban terméket frissítettél az admin felületen, de az ügyfelek még a régi árat látják – de csak 15 percig, utána automatikusan megjelenik az új ár. Melyik cache stratégiát alkalmazza valószínűleg a rendszer?

a) Cache nélküli közvetlen adatbázis-olvasás
b) TTL-alapú cache (lejárati idő)
c) Aktív invalidáció módosításkor
d) CDN cache

(Helyes: b – az automatikus lejárat jelzi a TTL mechanizmust)


8. Miért veszélyes ugyanolyan fájlnévvel felülírni egy képet, ha CDN is van a rendszerben?

a) A CDN nem tud képeket kezelni
b) A CDN cache a fájlnév alapján azonosítja a tartalmat, így a régi cache-elt verziót adja vissza az új tartalom helyett
c) A böngésző nem tud két azonos nevű fájlt kezelni
d) Adatbázis-hiba keletkezik azonos névnél

(Helyes: b)


9. Fejlesztő inkognitó módban más adatot lát, mint normál böngészőablakban. Mi a valószínű ok?

a) A szerver eltérő választ ad különböző IP-kről
b) Normál módban böngésző cache-ből tölt, inkognitóban friss lekérdezés
c) Az adatbázis véletlenszerű sorrendben adja az adatokat
d) Az alkalmazás kód hibás

(Helyes: b)


10. Melyik kijelentés IGAZ a szerver oldali cache-elésről?

a) Ha az adatbázisban közvetlenül módosítasz (SQL-lel), a szerver cache automatikusan frissül
b) A szerver cache csak statikus fájloknál alkalmazható
c) Ha az adatbázisban közvetlenül módosítasz, az alkalmazás cache-e nem frissül automatikusan
d) A szerver cache mindig gyorsabb, mint a böngésző cache

(Helyes: c – a cache invalidációt explicit triggerelni kell, a közvetlen DB módosítás ezt nem teszi meg)

Scroll to Top