Hallo? Dit is Jayon.
Vandaag ga ik uitleggen hoe ik cache instel. Ik schrijf deze post op basis van mijn eigen ervaringen in de praktijk, dus ik raad je aan om het als referentie te zien ㅎㅎ
Wat is Cache?
Cache is het opslaan van resultaten die later worden aangevraagd, zodat ze snel kunnen worden geserveerd. Met andere woorden, het is een techniek waarbij resultaten van tevoren worden opgeslagen en wanneer er een aanvraag binnenkomt, de cache wordt geraadpleegd in plaats van de DB of API te raadplegen om de aanvraag te verwerken. De achtergrond van deze cache is de Pareto-wet.
De Pareto-wet stelt dat 80% van de resultaten wordt veroorzaakt door 20% van de oorzaken. Raadpleeg de onderstaande afbeelding voor meer informatie!
Kortom, het is niet nodig om alle resultaten in de cache op te slaan. Door alleen de 20% van de resultaten die het meest worden gebruikt te cachen, kan de algehele efficiëntie worden verbeterd.
Welke gegevens moeten worden gecached?
Volgens de Pareto-wet mogen niet alle gegevens worden gecached, maar alleen de gegevens die echt nodig zijn. Welke gegevens moeten dan worden gecached?
Gegevens die vaak worden gelezen, maar zelden worden geschreven
Theoretisch gezien wordt er vaak gezegd dat "gegevens die vaak worden gelezen, maar zelden worden geschreven, moeten worden gecached", maar de criteria voor "vaak lezen" en "zelden schrijven" waren behoorlijk vaag.
Daarom onderzoek ik de te cachen gegevens met behulp van de volgende stappen.
- Ik controleer de top 5 van RDB query-aanroepen via een APM zoals DataDog.
- Daarin zoek ik naar query's voor het ophalen van gegevens en controleer ik van welke tabel deze gegevens worden opgehaald.
- Ik controleer hoe vaak de update-query voor die tabel wordt aangeroepen.
Door dit proces te volgen, kan ik controleren of er veel query's voor het ophalen van gegevens zijn, maar weinig update-query's. De tabel die ik in de praktijk heb gecontroleerd, had 1.740.000 query's voor het ophalen van gegevens per dag, maar de update-query's kwamen hooguit 500 keer voor. Dit is een duidelijke indicatie dat deze tabel geschikt is voor caching ㅎㅎ
Gegevens die gevoelig zijn voor updates
Gegevens die gevoelig zijn voor updates, betekenen dat het verschil tussen RDB en cache klein moet zijn. Bijvoorbeeld, informatie met betrekking tot betalingen is erg gevoelig voor updates, dus zelfs als het voldoet aan de bovengenoemde cachevoorwaarden, moet er goed over worden nagedacht of het wel moet worden toegepast.
Ik moest cache toepassen op een tabel met betrekking tot betalingen die aan beide kenmerken voldeed. Daarom heb ik cache niet toegepast op alle logica die deze tabel met betrekking tot betalingen gebruikt, maar heb ik besloten om cache gedeeltelijk toe te passen op relatief veilige logica waar geen betalingen plaatsvinden.
Lokale caching versus globale caching
Nu hebben we een idee van welke gegevens moeten worden gecached en de reikwijdte van de caching. Vervolgens moeten we nadenken over "waar" we de te cachen gegevens moeten opslaan. Over het algemeen kan dit in het lokale geheugen of op een aparte server zoals Redis worden gedaan.
Lokale caching
Lokale caching is een methode waarbij de te cachen gegevens worden opgeslagen in het geheugen van de applicatieserver. Meestal wordt Guava cache of Caffeine cache gebruikt.
Voordelen
- Omdat de cache wordt opgevraagd vanuit het geheugen op dezelfde server tijdens het uitvoeren van de applicatielogica, is de snelheid hoog.
- Eenvoudig te implementeren.
Nadelen
- Er kunnen verschillende problemen optreden als er meerdere instanties zijn.
Globale caching
Globale caching is een methode waarbij een aparte server, zoals Redis, wordt gebruikt om cachegegevens op te slaan.
Voordelen
- Omdat de cache wordt gedeeld tussen instanties, kan elke instantie dezelfde cachewaarde krijgen, zelfs als de cache door één instantie wordt gewijzigd.
- Wanneer een nieuwe instantie wordt gestart, hoeft de cache niet opnieuw te worden ingevoerd, omdat deze de bestaande cacheopslag kan gebruiken.
Nadelen
- Omdat er netwerkverkeer nodig is, is de snelheid lager dan bij lokale caching.
- Er zijn extra infrastructuurkosten omdat er een aparte cacheserver moet worden gebruikt.
Welke methode heb ik gekozen?
De applicatieserver van het bedrijf gebruikt momenteel een structuur met meerdere instanties, maar ik heb gekozen voor lokale caching.
Er zijn drie belangrijke redenen hiervoor.
- De te cachen gegevens die zijn opgeslagen in RDB zijn iets minder dan 40.000, dus zelfs als ze allemaal in het geheugen worden geladen, is het minder dan 4 MB.
- De prestaties van het ophalen van gegevens met betrekking tot betalingen moesten goed zijn.
- Hoewel Redis al beschikbaar is, brengt het opslaan van nieuwe cachegegevens in Redis extra infrastructuurkosten met zich mee.
Hoe wordt de cache bijgewerkt?
Als er meerdere applicatieservers zijn en lokale caching wordt gebruikt, kunnen de cachewaarden voor elke applicatieserver verschillen. Stel dat de cachegegevens die zijn opgeslagen op server A "1" zijn, maar de cachegegevens die zijn opgeslagen op server B zijn gewijzigd naar "2" door een wijziging op server B. In dit geval ontvangt de gebruiker verschillende waarden van server A en server B wanneer hij een aanvraag naar de load balancer stuurt.
Daarom moet de cache voor elke instantie automatisch worden verwijderd, zodat de gegevens opnieuw worden opgehaald uit RDB. Hiervoor wordt meestal TTL gebruikt.
Hoe moet TTL worden ingesteld?
TTL is de afkorting van Time To Live en is een instelling die de cache na een bepaalde tijd verwijdert. Als TTL bijvoorbeeld op 5 seconden is ingesteld, worden de cachegegevens na 5 seconden automatisch verwijderd. Daarna treedt er een cachemiss op en worden de gegevens opgehaald uit RDB en opgeslagen.
Hoe moet TTL dan worden ingesteld?
Lezen/schrijven vindt plaats op één cacheserver
Als lezen/schrijven plaatsvindt op één globale cacheserver zoals Redis, of op één applicatieserver met lokale caching, dan kan de waarde van TTL worden verhoogd tot een tijdseenheid of langer. De cache wordt toch bijgewerkt bij het schrijven en de server die gegevens van die cache ophaalt, krijgt altijd de meest recente gegevens.
In dat geval kan TTL worden uitgeschakeld en kan de cacheserver de cache geleidelijk wissen met behulp van het LRU-algoritme wanneer deze vol raakt.
Lezen/schrijven vindt plaats op meerdere cacheservers
Als lezen/schrijven plaatsvindt op meerdere globale cacheservers, of op meerdere applicatieservers met lokale caching, dan is het beter om TTL in te stellen op seconden tot minuten. Dit komt omdat er een kans bestaat dat oude gegevens worden gelezen van een cacheserver die de gewijzigde gegevens nog niet heeft weergegeven.
TTL wordt in verschillende contexten bepaald, maar hoe belangrijker de actualiteit is en hoe groter de kans op wijzigingen, hoe korter TTL moet zijn. Hoe minder belangrijk de actualiteit is en hoe kleiner de kans op wijzigingen, hoe langer TTL kan zijn.
Hoe heb ik TTL ingesteld?
De gegevens die ik wil cachen hebben betrekking op betalingen en hoewel ik cache niet op de strikte logica toepas waar betalingen daadwerkelijk plaatsvinden, is actualiteit van cruciaal belang vanwege de aard van betalingen. De kans op updates is echter klein, dus ik heb TTL voor de zekerheid op 5 seconden ingesteld.
Conclusie
Samengevat is de door mij gekozen cachingmethode als volgt:
- Gegevens met betrekking tot betalingen
- Zeer frequent opgevraagd, maar zelden gewijzigd.
- Cache toepassen op logica waarbij gegevens worden opgevraagd, maar geen betalingen plaatsvinden.
- Lokale caching toegepast en TTL is ingesteld op 5 seconden.
De volgende stap is het uitvoeren van prestatietests op de geïmplementeerde cachingmethode. Ik ben nog steeds aan het nadenken over hoe ik de prestatietests ga uitvoeren, dus ik zal dit in een latere post beschrijven!
Reacties0