Spring Boot Uygulamalarında Redis Cache Kullanımı

KATEGORİ

Çok fazla istek (request) yapılan bir sistem düşünelim. Sistemin yükünü nasıl hafifletebiliriz? İstek yapılan veriler sabit verilerse burada uygulayacağımız bir cache (önbellek) çözümü sistemin isteklere yanıt süresini ciddi miktarda azaltabilir ve sistem performansına olumlu etkide bulunabilir.

Cache (önbellek), sıklıkla kullanılan verilerin saklandığı bir bellek türüdür. İhtiyaç durumunda bu veriler hızlı bir biçimde kullanılabilir.

Redis, key-value tabanlı, açık kaynaklı bir in-memory veri depolama sistemidir. Bu sistem ile veriler sabit diskler yerine RAM gibi hızlı erişim sağlayan bellek alanlarında tutulur. Bu da verilere çok daha hızlı bir biçimde erişim imkanı sağlar.

Bu yazıda spring boot uygulamalarında redis kullanarak önbellekleme (cache) işleminin nasıl yapıldığından ve örnek bir uygulamanın performansına etkilerinden bahsedeceğim.

Windows üzerinde kurulum işlemleri için https://github.com/microsoftarchive/redis/releases adresinden msi dosyasını indirip kurulum adımlarını takip edelim. Kurulum yapılan klasöre git. redis-server.exe çalıştır. redis-cli.exe çalıştır. MacOs için https://redis.io/docs/install/install-redis/install-redis-on-mac-os/

Lettuce, Java uygulamalarının Redis sunucusuna bağlanmasını, etkileşimde bulunmasını ve veri alıp göndermesini sağlayan bir kütüphanedir.

Projeye redis bağımlılıklarını ekleyelim.

application.properties dosyasında Redis sunucusuna bağlanmak için gerekli konfigurasyonları ekleyelim.

spring.redis.host=localhost
spring.redis.port=6379

Bir REST api oluşturalım ve spring boot üzerinde redis cache işlemini yapalım. Uygulamayı test etmeye başlamadan önce redis’in ayakta olduğundan emin olalım. Servis çalışmıyorsa terminalde ya da komut satırında redis-server komutunu çalıştıralım.

Redis konfigurasyonunu yapalım. Bunun için RedisConfig dosyasını oluşturalım.

Bu sınıf redis bağlantısının kurulmasını ve önbellekleme işleminin yapılmasını sağlar. Redis sunucusuna bağlanmak için gerekli ayarlar application.properties dosyasından redisHost ve redisPort alanlarına çekilir. redisConnectionFactory() sunucuya bağlanmak için gerekli yapılandırmayı sağlar. cacheManager() metodu, Redis için önbellek yöneticisini oluşturur. Bu yönetici, önbellek işlemlerini yönetir. myDefaultCacheConfig() cache sürelerini belirler ve JSON değerleri Redis’te depolamak için yapılandırma sağlar.

Öncelikle name ve description alanlarını tutan CoffeeRequest ve CoffeeResponse veri transfer nesnelerini (sınıfları) oluşturalım.

Ardından Coffee sınıfımızı oluşturalım. Sınıfımızın id, name ve description değişkenleri olsun.

Service ve DAO sınıflarımızı oluşturalım.

@EnableCaching diyerek bu serviste önbellekleme işlemi yapılacağını belirtiriz. @Caheable, @CacheEvict, @CachePut annotation’larını kullanırız.

CoffeeController sınıfını oluşturalım.

Aşağıdaki örnek JSON kayıtları ekleyelim.

[
{
"name": "Black Coffee",
"description": "Svart kaffe är så enkelt som det kan bli med malda kaffebönor dränkta i hett vatten, serverat varmt. Och om du vill låta fancy kan du kalla svart kaffe med sitt rätta namn: café noir."
},
{
"name": "Latte",
"description": "Som den mest populära kaffedrycken där ute består latte av en skvätt espresso och ångad mjölk med bara en gnutta skum. Den kan beställas utan smak eller med smak av allt från vanilj till pumpa kryddor."
},
{
"name": "Caramel Latte",
"description": "Om du gillar latte med en speciell smak kan karamell latte vara det bästa alternativet för att ge dig en upplevelse av den naturliga sötman och krämigheten hos ångad mjölk och karamell."
},
{
"name": "Cappuccino",
"description": "Cappuccino är en latte som är gjord med mer skum än ångad mjölk, ofta med ett strö av kakaopulver eller kanel på toppen. Ibland kan du hitta variationer som använder grädde istället för mjölk eller sådana som tillsätter smakämnen också.",
},
{
"name": "Americano",
"description": "Med en liknande smak som svart kaffe består americano av en espresso skott utspätt med hett vatten."
},
{
"name": "Espresso",
"description": "Ett espressoskott kan serveras ensamt eller användas som grund för de flesta kaffedrycker, som latte och macchiato."
},
{
"name": "Macchiato",
"description": "Macchiaton är en annan espresso-baserad dryck som har en liten mängd skum på toppen. Det är det glada mellanrummet mellan en cappuccino och en doppio."
},
{
"name": "Mocha",
"description": "För alla chokladälskare där ute kommer ni att bli förälskade i en mocha. Mocha är en choklad-espressodryck med ångad mjölk och skum."
},
{
"name": "Hot Chocolate",
"description": "Under kalla vinterdagar får en kopp varm choklad dig att känna dig bekväm och lycklig. Den får dig också att må bra eftersom den innehåller energigivande koffein."
},
{
"name": "Chai Latte",
"description": "Om du letar efter en smakfull varm dryck mitt i vintern, välj chai latte. Kombinationen av kardemumma och kanel ger en underbar smak."
},
{
"name": "Matcha Latte",
"description": "Matcha latte är en grön, hälsosam kaffedryck med finkrossad matcha-te och mjölk, erbjuder mild sötma, en unik smak och en mild koffeinkick."
},
{
"name": "Seasonal Brew",
"description": "Säsongs kaffe med olika smaktoner som karamell, frukt och choklad"
},
{
"name": "Svart Te",
"description": "Svart te föddes i Kina. Det är tillverkat av blad från en växt som kallas Camellia och kan smaksättas olika med frukter till exempel. En trevlig, varm, smakfull och aromatisk dryck som passar till vardagen."
},
{
"name": "Islatte",
"description": "Iced latte är en kyld kaffedryck som görs genom att blanda espresso och kyld mjölk. Den serveras med isbitar och är även känd som cafè latte iced eller latte on the rocks."
},
{
"name": "Islatte Mocha",
"description": "Iced latte Mocha är en kombination av latte och mocha, som i sig är en kombination av choklad och kaffe. Den ger kalla dryckälskare en läcker upplevelse av choklad och kaffe."
},
{
"name": "Frapino Caramel",
"description": "Det är en blandad eller bättre sagt skakad kaffe med vispad grädde på toppen. Ett måste för varma sommardagar."
},
{
"name": "Frapino Mocka",
"description": "Ännu en berömd och utsökt kall dryck för dem som föredrar choklad. Tänk dig smaken av en shake med choklad och vispad grädde på toppen."
},
{
"name": "Apelsinjuice",
"description": "Vi har inget att säga om vår nypressade apelsinjuice. Du måste prova den själv."
},
{
"name": "Frozen Lemonade",
"description": "Frozen lemonade är en uppfriskande sommardryck som kombinerar färskpressad citronsaft, is och sötning till en svalkande, syrlig och sötsyrlig smaksensation."
},
{
"name": "Lemonad",
"description": "Var känd i Paris först och blev sedan mycket populär i hela Europa. Denna söta, färglösa, kolsyrade dryck görs genom att blanda citronsaft och kolsyrat vatten."
}
]

postman’da şu şekilde bir post isteği yapalım.

Eklediğim tüm elemanları görüntüleyelim ve çalışma sürelerini inceleyelim.

3.19 saniyede çalıştığını gördük. Tekrar aynı çağrıyı yaptığımızda eğer cache işlemi düzgün yapıldıysa çok daha kısa sürede sonuç dönmeli. Aşağıdaki görüntüdeki gibi tekrar çağrı yaptığımızda 50 ms içinde sonuç döndüğünü gördük. Peki şu anda spring boot cache mi yoksa redis cache mi kullanılıyor. Bunun için terminale gidip redis-cli komutunu çalıştırıyorum. Ardından keys * komutunu çalıştırdığımda coffees cache bilgisinin oluştuğunu görüyorum.

Belli bir id değeri ile bir kayıt almaya çalışalım ve çalışma süresini görelim.

Aynı sorguyu tekrar yaptığımızda cache sayesinde cevap süresinin 20 ms olduğunu görüyoruz.

Aşağıdaki controller methodlarını inceleyelim.

Service sınıfları içinde cache işlemlerinin yapılışını görelim. findAll ve findByNameContaining methodları aynı cache ismiyle kullanılır. Aranan name değerlerinin her biri için ayrı ayrı cache değerleri oluşturulur. findAll methodu sonucunda da simpleKey anahtarı oluşur. Redis üzerindeki görüntü için bir sonraki görüntüye bakalım.

“coffees::Cho” cache ifadesi içinde Cho geçen kahve aramaları için kullanılıyor. coffee::20 key değeri de 20 numaralı elemana ait cache’i gösteriyor.

Diyelim ki 19 numaralı kahvenin name ve description alanlarında güncelleme yapacağız. Burada mevcut durumda elimde coffee::19 gibi bir cache varsa bunu sıfırlamak gerekir. Bunun için CacheEvict’i kullanıyoruz.

PUT request ile bir güncelleme işlemi yapalım. Method service içinde update methodunu çağırdığında cache sıfırlanır. Sonra 19 numaralı kayıt get ile çağrıldığında yanıt süresinin arttığı görülür.

Yine 19 numaralı kaydı sildiğimizi düşünelim. Burada da CacheEvict ile 19 numaralı kayıt için oluşturulan cache silinir.

Tüm kayıtlar silindiğinde de bütün coffee cache değerleri silinir.

Controller PUT ve DELETE methodları şu şekildedir: