Javaでインメモリでキャッシュしたくなったときによく使うCaffeineだが、エントリの有効期限に jitterを入れたくなることがある。 前やったときどうやったか忘れてしまったので、ここにメモしておく。
インターフェースとしては、Expiryというインターフェースがあり、以下のような形で使う。
Caffeine.newBuilder() .expireAfter(new JitterExpiry<>(Duration.ofSeconds(30))) .build();
なお、今回試しで書いてみた実装がこれ。コンストラクタで指定されたdurationをベースに 0.5を係数にjitterを入れる実装になっている。
ちなみに、それぞれのメソッドの戻り値は、nano秒である必要がある。
public class JitterExpiry<K, V> implements Expiry<K, V> { private final long duration; private final SecureRandom secureRandom = new SecureRandom(); private JitterExpiry(Duration duration) { this.duration = duration.toNanos(); } @Override public long expireAfterCreate(K key, V value, long currentTime) { return (long) (duration * (2 * secureRandom.nextDouble() - 1)); } @Override public long expireAfterUpdate(K key, V value, long currentTime, @NonNegative long currentDuration) { return (long) (duration * (2 * secureRandom.nextDouble() - 1)); } @Override public long expireAfterRead(K key, V value, long currentTime, @NonNegative long currentDuration) { return currentDuration; } }
まだリリースされていないが(ver. 3.1.8現在)、以下の変更でstaticメソッドが追加されているため、これがリリースされた際にはより簡潔に書けるようになるはずだ。
Add Expiry static factory methods (fixes #1499) · ben-manes/caffeine@49df4e9 · GitHub