Spring Boot ve Caching

Fatma Delen
5 min readMar 21, 2021

--

Merhabalar, bugün sizlere Caching’ten ve Redis’ten bahsedeğim.

Caching, sistemin gelen her request için veritabanına gitmesini engeller. Eğer bir sorgunun sonucu cache’de varsa, daha önceden edinilmişse, bunu cache’dan getirerek veritabanı trafiği oluşmasını önler. Vereceğimiz şartlara göre cache’deki verinin veritabanına aktarılması da mümkündür.

Çok fazla sorgulama yapılan uygulamalarda sorgu caching’i yaparak önemli bir performans artışı sağlanabilmektedir.

Hangi veriler önbelleğe alınmalıdır?

Bir kaç örnek verecek olursam:

— Bir e-ticaret sitesinde bulunan ürünlerin listesi.

— Sıklıkla değiştirilmeyen veriler.

— Sık kullanılan herhangi bir veritabanı okuma sorgusu(sonuç her aramada en azından belirli bir süre için değişmez.)

Caching Türleri

In-memory caching

Uygulamanın performansını artırmak için en sık kullanılan caching türüdür. Memcached ve Redis gibi in-memory cacheler, uygulamanız ve veri depolama alanınız arasındaki key-value depolarıdır. Veriler RAM’de tutulduğundan, tipik veritabanlarından çok daha hızlıdır.

Database Caching

Veritabanları genellikle genel bir kullanım durumu için optimize edilmiş varsayılan bir yapılandırmada bir miktar önbelleğe alma(caching) içerir. Bu ayarları belirli kullanım modelleri için değiştirmek performansı daha da artırabilir. Bu alanda popüler olanlardan biri, Hibernate veya herhangi bir ORM frameworkünün birinci seviye önbelleğidir(cache).

Web Server Caching

Web serverlar da istekleri önbelleğe alabilir ve uygulama sunucularına başvurmak zorunda kalmadan yanıtları geri verebilir.

CDN Caching

Cacheler, istemci(client) tarafında (işletim sistemi veya tarayıcı), sunucu(server) tarafında veya farklı bir önbellek katmanında bulunabilir.

Cache Provider(Önbellek Sağlayıcıları)

  • JCache (JSR-107) (EhCache 3, Hazelcast, Infinispan, …)
  • EhCache 2.x
  • Hazelcast
  • Infinispan
  • Couchbase
  • Redis
  • Caffeine
  • Simple cache

Spring Boot ve Caching

Şimdiiii projemizi yapmaya başlayalım. Bu örnekte Spring Boot da varsayılan caching i nasıl etkinleştirebileceğimizi göreceğiz. Son olarak, aynı yöntemin tekrarlanan çağrısı üzerinde uygulama performansını test edeceğiz.

Öncelikle Spring Initializr dan bir Spring Boot projesi oluşturalım.

Eveett şimdi kodumuzu yazmaya başlayabiliriz. Öncelikle application.yml dosyamızda database ayarlarını yapalım.

Daha sonra Person adında bir class oluşturalım.

Ardından Repository classımızı oluşturalım.

Ardından service classımızı oluşturalım.

@Cacheable: Cevabı önbelleğe alır.
@CachePut: Önbelleğin güncellenmesi gereken durumlar için kullanılır.
@CacheEvict: Bu anotasyon, eski veya kullanılmayan verileri önbellekten kaldırmak için kullanılır.

@Cacheable anotasyonu, ilk metod çağrısından sonra cevabı önbelleğe alır ve sonraki çağrılarda önbellekten cevap dönmemizi sağlar. Böylece, persons listesini her istediğimizde 2 saniye beklemek zorunda kalmayız. Anotasyona value olarak persons değerini veriyoruz. (Daha sonra bu önbelleği yönetebilmemiz için lazım olacak.)

@CachePut, @Cacheable ve @CacheEvictanotasyonlarında bulunan key değeri, önbellekte hangi değerle işlem yapacağımızı bildirir. Bu key değerini setlemek için SpEL expression kullanılabilir.

Bazen, bir data her zaman önbelleğe almak için uygun olmayabilir. @CachePut, @Cacheable ve @CacheEvictanotasyonlarında bulunan condition parametresi, true veya false olarak değerlendirilen bir SpEL ifadesini alan koşullu parametre aracılığıyla bu tür işlevselliği destekler. True ise, data cache’e alınır değilse, data cache’e alınmamış gibi davranır.

@CachePut, @Cacheable ve @CacheEvictanotasyonlarında bulunan unless parametresi aracılığıyla, condition parametresinden farklı olarak yapılan girdiden ziyade çıktıya göre cache’e almayı kontrol edebiliriz.

@CacheEvictanotasyonunda bulunan allEntries parametresi, cache(ler) içindeki tüm entrylerin kaldırılıp kaldırılmayacağını belirtir.

SpEL Expression

Ardından bu classımızı çağıracak apimizin olduğu controller classımızı oluşturalım.

Şimdi Application classımıza “@EnableCaching” anotasyonunu ekleyerek sonuçlarımızı kontrol edelim…

NOT: İstediğimiz zaman bu özelliği devre dışı bırakmak istersek Caching ile işaretlediğimiz tüm anotasyonları silmemize gerek yok. Spring Boot uygulamamızın application.yml dosyasına aşağıdaki kodu yazmamız yeterlidir.

Postman aracılığıyla apilerimizi test edelim… Öncelikle bir kaç tane person create edelim ardından tüm personları getirecek olan apiyi test edelim.

İlk isteğimizi attığımızda 2.33 saniye sonra response ‘un döndüğünü görüyoruz.
2. isteğimizi attığımızda 18 milisaniye içinde response’un döndüğünü görüyoruz. Yani bu demek oluyor ki veriler başarıyla cache eklendi.

Şimdi ilgili name’e ait olan person’ı getirelim ve sonuçlarımızı görelim.

İlk isteğimizi attığımızda 3.12 saniye sonra response ‘un döndüğünü görüyoruz.
2. isteğimizi attığımızda 15 milisaniye sonra response ‘un döndüğünü görüyoruz.

Şimdi conditionlara uymayan bir person için deneme yapalım.( condition = “#name.length() > 4”, unless = “#result.age < 24”)

İlk isteğimizi attığımızda 2.02 saniye sonra response ‘un döndüğünü görüyoruz.
2. isteğimizi attığımızda 2.01 saniye sonra response ‘un döndüğünü görüyoruz. Çok bir zaman farkı olmadığını görüyoruz (Bu demek oluyor ki conditionlara uymayan bir data)

…/person/cacheClear veya …/person/delete/all apisine istek attığımızda cache de bulunan dataları silebiliriz.

Şimdi Redis’e gelelim :)

Spring Boot ve Redis

Redis, bir NoSQL veritabanıdır. Kullanıldığı yaygın alanlardan birisi Caching işlemleridir. Gecikmeyi azaltmak, uygulamanın verimini artırmak için bir in-memory cache(önbellek) olanağı sağlar.

NOT: Redis için, 64 bitlik bir sistemde veri depolama konusunda bir sınırlama yoktur, ancak 32 bit sistemde yalnızca 3 GB depolayabilir.

Projemizi yazmaya başlamadan önce docker image’i ayağa kaldıralım. Bunun için terminali açıp “ docker run -p 6379:6379 — name fd-redis -d redis” komutunu yazalım. Komut çalıştırıldığında Docker Hub’dan Redis image’ı çekilmiş ve ayağa kaldırılmış olacak.

Bunu yapmadan önce Docker ile alakalı yazıma göz atabilirsiniz.

“docker ps” komutu ile ayakta olan container’ları listeleyelim.

Şimdi kodumuzu yazmaya başlayabiliriz…

Öncelikle Spring Initializr dan bir Spring Boot projesi oluşturalım.

Projeyi indirdikten sonra build.gradle dosyasına “implementation group: ‘redis.clients’, name: ‘jedis’, version: ‘2.8.0’” ekleyelim. Bu sayede Spring Boot’un Redis’e bağlanması için gerekli bir dependency eklemiş olduk.

Spring Boot Redis Configuration

1- Java Tabanlı Configuration

Redis bağlantı ayarlarını tanımlamak için bir konfigürasyon sınıfı oluşturmamız gerekiyor.

RedisConfig adında bir class oluşturalım.

2- Property File Tabanlı Configuration

Spring Boot uygulamasında redis önbelleğini yapılandırmak için gereken application.yml içeriği:

Şimdi Application classımıza “@EnableCaching” anotasyonunu ekleyerek sonuçlarımızı kontrol edelim…

Diğer tüm kodları Github profilimde bulabilirsiniz :)

Postman aracılığıyla apilerimizi test edelim…

İlk isteğimizi attığımızda 2.34 saniye sonra response ‘un döndüğünü görüyoruz.

2. isteğimizi atıp sonuçları görelim.

2. isteğimizi attığımızda 23 milisaniye sonra response ‘un döndüğünü görüyoruz. Bu demek oluyor ki cacheleme olayını başarıyla gerçekleştirdik :)

Tüm kodlar:

--

--