経緯
- Spring-bootを使ったwebアプリケーションで、Cacheを使用する必要が出てきた際に調べたことを簡単にまとめる
調べたこと
Spring-bootの公式で紹介しているCacheの方法は複数ある模様。
その中でも、Caffeineが導入コストが低そうである。
検証
実際に使ってみないとパフォーマンスがわからなかったので動かしてみることにした。
用意したもの
- IntelliJ IDEA
- JAVA 1.8
- Spring-boot(2系)
まずgradleに設定を追加してみる
build.gradle
compile(org.springframework.boot:spring-boot-starter-cache)
compile(com.github.ben-manes.caffeine:caffeine)
次にconfigクラスを作る
CacheConfig.java
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableCaching
public class CacheConfig {
}
cacheをかけたいクラスに設定を追加する
HistoryService.java
@Service
public class HistoryService {
@Cacheable("HistoryCache")
public String getHistories(String name, OffsetDateTime date) {
// 過去データの取得
}
あとはymlで設定をいじる
application.yml
spring:
cache:
cache-names: HistoryCache
caffeine:
spec: maximumSize=100, expireAfterWrite=60s
上記の設定で動いているのかわからなかったので、、、
HistoryService.java
@Service
public class HistoryService {
@Cacheable("HistoryCache")
@Slf4j
public String getHistories(String name, OffsetDateTime date) {
long start = System.currentTimeMillis();
//処理内容は省略
// ログをだす
long end = System.currentTimeMillis();
log.info("cache is not used. exec time was : " end - start + "ms");
}
実行結果
- 1回目はログが吐かれたことを確認
- 1回目から30秒後に2回目を実行したところログが吐かれないことを確認
- 3回目は1回目から65秒後に実行したところログが吐かれたことを確認
ymlの設定を変えてみる
application.yml
spring:
cache:
cache-names: HistoryCache
caffeine:
spec: maximumSize=100, expireAfterAccess=60s
実行結果
- 1回目はログが吐かれたことを確認
- 1回目から30秒後に2回目を実行したところログが吐かれないことを確認
- 3回目は2回目から55秒後に実行したところログが吐かれないことを確認
追記(2018/11/02)
- 同一クラス内のメソッドを呼び出してる場合だと、キャッシュがそもそも効かないっぽいので、別のサービスとして切り出してあげる必要がありそう
- 下記を参照してください
HistoryService.java
@Service
public class HistoryService {
public void hogehoge() {
// 途中省略
//ここで同一クラス内を呼び出してるんでキャッシュが効かないっぽい
String hogehoge = getHistories("太郎","20181102");
}
@Cacheable("HistoryCache")
@Slf4j
public String getHistories(String name, OffsetDateTime date) {
long start = System.currentTimeMillis();
//処理内容は省略
// ログをだす
long end = System.currentTimeMillis();
log.info("cache is not used. exec time was : " end - start + "ms");
}
###設定できる値について
ちなみに、この前まで時間を設定するところで秒数しか設定できないと思っていましたが、秒以上(すなわちms以下はダメ)であれば分・時・日あたりは設定できるっぽいです。
まとめ
- キャッシュはメソッドの引数ごとに持っている模様
(引数の値が異なれば引数ごとにキャッシュが作られる) - expireAfterAccessを設定すると、メソッドが最後に呼ばれた時から設定した時間でキャッシュが消える
- expireAfterWriteを設定すると、キャッシュが最初に作られた時から設定した時間でキャッシュが消える
- ローカルで実行する分にはほとんど差分は見られなかったが、開発環境だとアプリケーションの規模にもよるが、全体の実行時間で5秒前後短縮された