きり丸の技術日記

技術・エンジニアのイベント・資格等はこちらにまとめる予定です

Spring Cacheでキャッシュを使って高速化する

きり丸アドベントカレンダー2020の21記事目です。


弊社の試験環境のシステムには、月跨ぎや年跨ぎのテストを行いやすいように業務日付という概念があります。処理日等の項目を業務日付に合わせて連携しないと、対向システムのバリデーション等にひっかかってしまいます。他にも面倒な点として、月跨ぎや年跨ぎのテストをやりやすいようにするための概念ですので、業務日付は毎日変わります。

ですので、現在のシステムでは業務日付を導き出せるように「現在日付 + X日 = 業務日付」の「X日」をDBに保存しています。

ただし、1回のリクエストで複数回の業務日付をDBから取得する必要があるので、何もしなければ無駄にパフォーマンスが悪くなってしまいます。業務日付は試験のためのロジックで、本番環境は現在日付と同じです。試験のための項目で、本番環境の性能悪化させてしまうのは悪手です。

そういう時に、データをキャッシュすることで高速化が見込めます。

今回の記事ではSpringでキャッシュする仕組みをSpring Cacheで実装します。

ゴール

  • Spring Cacheで目的の値をキャッシュにする
  • キャッシュをクリアする

できないこと

  • キャッシュを更新する

環境

  • Java
    • 15
  • org.springframework.boot:spring-boot-starter-cache
    • 2.4.0
  • Lombok

手順

Spring Cacheを依存関係に含める


Spring Cacheを依存関係に含めます。

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-cache'
}

Spring Cacheを有効にする


@SpringBootApplicationを付与しているファイルに対して、@EnableCachingを付与します。

@SpringBootApplication
@EnableCaching
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

業務日付をキャッシュにする


@Cachenableでキャッシュを登録します。今回はパラメータが無いですが、パラメータがある場合はパラメータがキャッシュのキーになります。初回実行時はキャッシュが無いので、業務日付を導くための「X日」をDBから取得します。2回目以降はキャッシュがあるので、DBからではなくキャッシュから読み込みます。

@CacheEvictでキャッシュを削除します。業務日付が更新されたタイミングでキャッシュを削除することで、古いキャッシュを読み込ませることはありません。

@Repository
@RequiredArgsConstructor
public class BusinessDateComponentImpl implements BusinessDateComponent {
  private final BusinessDateRepository businessDateRepository;

  @Cacheable("businessDate")
  @Override
  public int getBusinessDate() {
    return businessDateRepository.getBusinessDate();
  }

  @CacheEvict("businessDate")
  @Override
  public void deleteCache() {
  }
}

その他にもキャッシュを更新するためのCachePutがあります。

ただし、今回の「業務日付をキャッシュ化する」という目的では、パラメータが無いせいかうまく更新できませんでした。他の記事で参考にしていただけると助かります。

アノテーション 説明
Cacheable キャッシュを登録する
CacheEvict キャッシュをクリアする
CachePut キャッシュを更新する

動作確認用


今回の記事とは直接関係がありませんが、キャッシュが効いていることの確認するためのロジックをGitHubのソースに含めています。今回の記事で検証した結果を次に記します。

// 業務日付の確認
curl -X GET http://localhost:8080/v1/businessDate/ -u admin:pass
// 業務日付のキャッシュ削除
curl -X GET http://localhost:8080/v1/businessDate/clear -u admin:pass

結果:

curl -X GET http://localhost:8080/v1/businessDate/ -u admin:pass
3000 # DBの値
# DBを更新して300にする
curl -X GET http://localhost:8080/v1/businessDate/ -u admin:pass
3000 # キャッシュの値
# 業務日付のキャッシュ削除
curl -X GET http://localhost:8080/v1/businessDate/clear -u admin:pass

curl -X GET http://localhost:8080/v1/businessDate/ -u admin:pass
300

ソースコード

アドベントカレンダー21日目。
github.com

終わりに

正直なところ、キャッシュは最終手段だととらえているのであまり使いたくはありません。万が一にでもキャッシュが更新されていないと古いデータを参照してしまいますからね…。

フロントエンドではキャッシュのデータを参照しているせいでABテストができない、障害が発生した等の苦労話もありますし。

致命的な性能悪化が起きた、または最悪古いデータを参照してもあまり影響が出ない今回のような要件でのみ、Spring Cacheを活かして活用したいです。


この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

参考記事

敬称略

4.2. キャッシュの抽象化(Cache Abstraction macchinetta.github.io

公式リファレンス:キャッシュ spring.pleiades.io

類似記事

きり丸アドベントカレンダー2020 adventar.org

きり丸のHerokuページ
https://kirimaru-todoapp.herokuapp.com/

22日目のアドベントカレンダーの記事 https://nainaistar.hatenablog.com/entry/2020/12/22/083000nainaistar.hatenablog.com

f:id:nainaistar:20201109133010p:plain