Üdvözlet! Jayon vagyok.
Ma a cache beállításának kritériumait szeretném elmagyarázni. Mivel a saját gyakorlati tapasztalataim alapján írok, kérlek, tekintsd ezt pusztán tájékoztató jellegűnek ㅎㅎ
Mi az a Cache?
A cache lényege, hogy a későbbi kérések eredményét előre eltárolja, és így gyorsan kiszolgálja azokat. Vagyis előre eltárolja az eredményeket, és amikor egy kérés érkezik, ahelyett, hogy a DB-hez vagy API-hoz fordulna, a cache-hez fér hozzá, és onnan dolgozza fel a kérést. Ennek a cache-nek a hátterében a Pareto-elv áll.
A Pareto-elv azt jelenti, hogy az eredmények 80%-a a kiváltó okok 20%-ának köszönhető, és érdemes lehet a lenti képet is megtekinteni!
Vagyis a cache-nek nem kell minden eredményt tárolnia, elég, ha a szolgáltatás során leggyakrabban használt 20%-ot tárolja, ezáltal az egész rendszer hatékonyságát növelve.
Milyen adatokat érdemes tárolni a cache-ben?
A Pareto-elv alapján nem szabad minden adatot a cache-be helyezni, csak a valóban szükségeseket. De akkor mely adatokat érdemes tárolni?
Azok az adatok, amelyeket gyakran olvasunk, de ritkán írunk
Elméletileg gyakran hallani, hogy „azokat az adatokat érdemes cache-be helyezni, amelyeket gyakran olvasunk, de ritkán írunk”, de a „gyakran olvasott” és a „ritkán írt” kritériumok meglehetősen homályosak voltak.
Ezért én a következő lépéseket követem a cache-be helyezendő adatok meghatározásakor.
- Az APM eszközök (pl. DataDog) segítségével megnézem az RDB lekérdezések TOP 5-ös listáját.
- Ezek közül kiválasztom a lekérdezéseket, és megnézem, hogy melyik táblából származnak.
- Megvizsgálom, hogy az adott tábla frissítési lekérdezései milyen gyakran hívódnak meg.
Ez a folyamat arról szól, hogy megvizsgáljuk, mely adatokat kérdezik le gyakran, de ritkán frissítik. A gyakorlatban egy táblánál azt láttam, hogy naponta 1,74 millió lekérdezés történik, de a frissítési lekérdezések száma maximum 500 volt. Ilyen esetben bárki számára egyértelmű, hogy ez a tábla alkalmas a cache-be helyezésre ㅎㅎ
Azok az adatok, amelyek érzékenyek a frissítésre
Azok az adatok, amelyek érzékenyek a frissítésre, azt jelentik, hogy az RDB és a cache közötti eltérésnek rövidnek kell lennie. Például a fizetési információkkal kapcsolatos adatok esetében rendkívül fontos a frissítés, ezért még akkor is, ha megfelelnek a fenti cache feltételeknek, meg kell fontolni a használatukat.
A fenti két tulajdonságnak megfelelő fizetési információkkal kapcsolatos táblákat kellett cache-be helyeznem. Ezért nem alkalmaztam a cache-t minden olyan logikára, amely a fizetési táblákat használja, hanem csak a viszonylag biztonságosabb logikákra, ahol a fizetés nem történik meg.
Lokális cache vs. globális cache
Most már tudjuk, hogy milyen adatokat és milyen mértékben érdemes cache-be helyezni. De hol tároljuk ezeket az adatokat? Általában a lokális memóriába vagy egy külön szerverre, például Redis-be tárolhatjuk.
Lokális cache
A lokális cache azt jelenti, hogy az alkalmazásszerver memóriájában tároljuk a cache-be helyezendő adatokat, és általában a Guava cache vagy a Caffeine cache használatos.
Előnyök
- Az alkalmazás logikájának végrehajtása közben azonnal lekérdezhető a cache ugyanazon a szerveren lévő memóriából, így nagyon gyors.
- Könnyen implementálható.
Hátrányok
- Ha több példány fut, akkor több probléma merül fel.
Globális cache
A globális cache azt jelenti, hogy külön szerveren tároljuk a cache adatokat, például Redis-ben.
Előnyök
- A példányok megosztják a cache-t, így ha az egyik példány módosítja a cache-t, akkor minden példány a módosított értéket fogja látni.
- Egy új példány indításakor nem kell feltölteni a cache-t, mert már létezik egy tároló, amelyhez hozzáférhet.
Hátrányok
- Hálózati forgalom szükséges, így lassabb, mint a lokális cache.
- Külön cache szerver szükséges, ami infrastruktúra költségeket generál.
Melyiket választottam?
A jelenlegi cég alkalmazásszervere több példányban fut, de mégis a lokális cache-t választottam.
Ennek három fő oka van.
- Az RDB-ben tárolt cache-be helyezendő adatok száma körülbelül 40 000, ami a memóriába betöltve 4 MB-nál kevesebb.
- A fizetési adatok lekérdezésének gyorsnak kell lennie.
- Bár már van Redis, a cache új Redis-be történő tárolása további infrastruktúra költségeket generál.
Hogyan frissítsük a cache-t?
Ha több alkalmazásszerverünk van, és lokális cache-t használunk, akkor a cache értékei eltérhetnek a különböző alkalmazásszervereken. Például az A szerver cache-ben tárolt érték „1” lehet, míg a B szerver cache-ben tárolt érték „2”, mert a B szerver módosította. Ebben az esetben, ha a felhasználó a terheléselosztónak (load balancer) küld egy kérelmet, akkor az A és B szerverek különböző értékeket küldenek vissza.
Ezért minden példányban automatikusan el kell távolítani a cache-t, és az RDB-ből kell lekérdezni az adatokat. Ehhez a TTL-t használjuk.
Milyen értéket adjunk meg a TTL-nek?
A TTL (Time To Live) azt jelenti, hogy egy adott idő elteltével töröljük a cache-t. Például, ha a TTL értéke 5 másodperc, akkor a cache adatok 5 másodperc múlva automatikusan törlődnek. Ezután, ha cache-hiány lép fel, lekérdezzük az adatokat az RDB-ből, és eltároljuk a cache-ben.
De akkor mekkora legyen a TTL értéke?
Ha a read/write műveletek egy cache szerveren történnek
Ha a read/write műveletek egy globális cache szerveren, például Redis-ben, vagy egy lokális cache-t használó alkalmazásszerveren történnek, akkor a TTL értéke akár órákra is növelhető. Mindenesetre a write művelet során a meglévő cache frissül, és a szerver mindig a legfrissebb adatokat fogja látni.
Ebben az esetben nem is kell beállítani a TTL-t, hanem a cache szerver automatikusan törölheti a cache-t, ha megtelik, például az LRU algoritmus használatával.
Ha a read/write műveletek több cache szerveren történnek
Ha a read/write műveletek több globális cache szerveren vagy több, lokális cache-t használó alkalmazásszerveren történnek, akkor a TTL értéke másodpercekben vagy percekben legyen. Ez azért fontos, mert előfordulhat, hogy a módosított adatokat még nem tükröző, elavult adatokat olvasunk be egy cache szerverről.
A TTL értéke sok tényezőtől függ, de minél fontosabb a frissítés és minél nagyobb a változás valószínűsége, annál rövidebb legyen a TTL. Minél kevésbé fontos a frissítés és minél kisebb a változás valószínűsége, annál hosszabb lehet a TTL.
Hogyan állítottam be a TTL-t?
A cache-be helyezendő adatok fizetési adatok, és bár a fizetéshez kapcsolódó szigorú logikákban nem használunk cache-t, a fizetési adatok természetüknél fogva érzékenyek a frissítésre. Ugyanakkor a módosítás valószínűsége alacsony, ezért a TTL-t 5 másodpercre állítottam be, ami biztonságosabb.
Következtetés
Összefoglalva, a választott cache-elési módszer a következő:
- Fizetési adatok
- Nagyon gyakori lekérdezések, de ritka módosítások.
- Csak azokban a logikákban alkalmazzuk a cache-t, amelyekben nem történik fizetés, de lekérdezések vannak.
- Lokális cache-t használunk, és a TTL 5 másodperc.
A következő lépés a cache-elési módszer teljesítményének tesztelése lesz. Még nem döntöttem el pontosan, hogyan fogjuk végrehajtani a teljesítménymérés tesztelését, de erről egy későbbi bejegyzésben fogok írni!
Hozzászólások0