SpringBootのキャッシングをRedisで使ってみる

例えば、DBから取得した結果を返却するというメソッドがあるとする。 このメソッドに@Cacheableを付与すると、検索結果をキャッシュに格納してくれて次回呼び出し時はキャッシュで保持しているデータを返却してくれる。 基本的にキャッシュにデータがある限りDBへのアクセスは行わず、キャッシュが消されると再びDBにアクセスして再度キャッシュする。 マスタデータの保持なんかで便利そう。

準備

build.gradle

・下記を追加

 implementation 'org.springframework.boot:spring-boot-starter-cache:2.5.4'
    implementation 'org.springframework.boot:spring-boot-starter-data-redis:2.5.4'

application.yml

・キャッシュプロバイダーはRedisを使用する

  cache:
    type: redis
  redis:
    host: localhost
    port: 16379
    database: 0
    password: 
    timeout: 3000

SampleApplication.java

・@EnableCachingでキャッシュを有効化

@SpringBootApplication
@EnableScheduling
@EnableCaching
public class SampleApplication {

UserCacheObject.java

・キャッシュ用オブジェクト

package sample.service.cache;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

import sample.service.common.utils.JsonUtils;
import sample.service.domain.repository.UserRepository;
import sample.service.domain.repository.model.User;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Component
public class UserCacheObject {

    private final UserRepository userRepository;

    @Cacheable(cacheNames = "sample-cache", key = "#key")
    public String findByUserId(Long userId, String key) {
        User user = userRepository.findById(userId);

        return JsonUtils.convertToJson(user);
    }
}

UserCacheBL.java

ビジネスロジックインタフェース

package sample.service.domainbl;

import sample.service.domain.repository.model.User;

public interface UserCacheBL {
    User findById(Long userId);
}

UserCacheBLImpl.java

ビジネスロジック実装クラス

package sample.service.domainbl.impl;

import org.springframework.stereotype.Component;

import sample.service.cache.UserCacheObject;
import sample.service.common.utils.JsonUtils;
import sample.service.domain.repository.model.User;
import sample.service.domainbl.UserCacheBL;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Component
public class UserCacheBLImpl implements UserCacheBL {

    private final UserCacheObject userCacheObject;

    @Override
    public User findById(Long userId) {
        String json = userCacheObject.findByUserId(userId, "User::" + userId);
        return JsonUtils.convertFromJson(json, User.class);
    }

}

ScheduledTasks.java

・スケジュールタスクでビジネスロジックを呼び出す

package sample.service.common.tasks;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import sample.service.common.utils.DateUtils;
import sample.service.domain.repository.model.User;
import sample.service.domainbl.UserCacheBL;

import lombok.RequiredArgsConstructor;

@Component
@RequiredArgsConstructor
public class ScheduledTasks {
    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledTasks.class);

    private final UserCacheBL userCacheBL;

    @Scheduled(initialDelay = 10000, fixedRate = 1000)
    public void doSomething() {
        User user = userCacheBL.findById(5L);
        LOGGER.info("### User : {}", user);

        LOGGER.info("### This time is : {}", DateUtils.format(new Date()));
    }
}

結果

こんな感じでRedisに格納された。

127.0.0.1:6379> keys *
1) "sample-cache::User::1"
127.0.0.1:6379> get sample-cache::User::1
"\xac\xed\x00\x05t\x00\xcf{\"id\":1,\"userName\":\"Jack\",\"mailAddress\":\"jack@hoge.example.jp\",\"password\":\"8bb0cf6eb9b17d0f7d22b456f121257dc1254e1f01665370476383ea776df414\",\"registTime\":1629500509000,\"updateTime\":1629500509000,\"deleted\":0}"
127.0.0.1:6379> del sample-cache::User::1
(integer) 1
127.0.0.1:6379> keys *
1) "sample-cache::User::1"