これを少し煮詰めましょう。アプリケーションはキャッシュを使用します(Redisで実装されます)。 Redis接続が古くなっている/閉じられているなどの場合は、アプリケーションでキャッシュをバイパスし、(おそらく)基盤となるデータストア(RDBMSなど)に直接アクセスする必要があります。アプリケーションのサービスロジックは次のようになります...
@Service
class CustomerService ... {
@Autowired
private CustomerRepository customerRepo;
protected CustomerRepository getCustomerRepo() {
Assert.notNull(customerRepo, "The CustomerRepository was not initialized!");
return customerRepo;
}
@Cacheable(value = "Customers")
public Customer getCustomer(Long customerId) {
return getCustomerRepo().load(customerId);
}
...
}
SpringコアのCachingAbstractionでキャッシュの「ミス」を確認するために重要なのは、返される値がnullであるということだけです。そのため、Spring Caching Infrastructureは、実際のServiceメソッド(つまり、getCustomer)の呼び出しに進みます。 getCustomerRepo()。load(customerId)呼び出しが返されることに注意してください。また、Springのキャッシングインフラストラクチャが値をキャッシュしようとする場合も処理する必要があります。
シンプルに保つという精神で 、AOPなしで実行しますが、AOPを使用してもこれを達成できるはずです(選択)。
必要なのは、SDRCacheManager実装を拡張する「カスタム」RedisCacheManagerだけです...
package example;
import org.springframework.cache.Cache;
import org.springframework.data.redis.cache.RedisCacheManager;
...
class MyCustomRedisCacheManager extends RedisCacheManager {
public MyCustomerRedisCacheManager(RedisTemplate redisTemplate) {
super(redisTemplate);
}
@Override
public Cache getCache(String name) {
return new RedisCacheWrapper(super.getCache(name));
}
protected static class RedisCacheWrapper implements Cache {
private final Cache delegate;
public RedisCacheWrapper(Cache redisCache) {
Assert.notNull(redisCache, "'delegate' must not be null");
this.delegate = redisCache;
}
@Override
public Cache.ValueWrapper get(Object key) {
try {
delegate.get(key);
}
catch (Exception e) {
return handleErrors(e);
}
}
@Override
public void put(Object key, Object value) {
try {
delegate.put(key, value);
}
catch (Exception e) {
handleErrors(e);
}
}
// implement clear(), evict(key), get(key, type), getName(), getNativeCache(), putIfAbsent(key, value) accordingly (delegating to the delegate).
protected <T> T handleErrors(Exception e) throws Exception {
if (e instanceof <some RedisConnection Exception type>) {
// log the connection problem
return null;
}
else if (<something different>) { // act appropriately }
...
else {
throw e;
}
}
}
}
したがって、Redisが利用できない場合、おそらく最善の方法は、問題をログに記録し、サービスの呼び出しを実行させることです。明らかに、これはパフォーマンスを低下させますが、少なくとも問題が存在するという認識を高めます。明らかに、これはより堅牢な通知システムに結び付けることができますが、それは可能性の大まかな例です。重要なのは、アプリケーションサービスが依存している他のサービス(Redisなど)が失敗している可能性がある間、サービスは引き続き利用できるということです。
この実装では(以前の説明と比較して)、基になる実際のRedisCache実装に委任して例外を発生させ、Redisに問題が存在することを十分に理解し、例外を適切に処理できるようにすることを選択しました。ただし、検査時に例外が接続の問題に関連していることが確実な場合は、「null」を返して、Spring Caching Infrastructureをキャッシュの「ミス」であるかのように進めることができます(つまり、Redis接続の不良==キャッシュミス、この場合)。
GemFireとPivotalの顧客の1人のために「カスタム」CacheManager実装の同様のプロトタイプを作成したので、このようなものがあなたの問題に役立つことを私は知っています。その特定のUCでは、キャッシュの「ミス」は、アプリケーションドメインオブジェクトの「古いバージョン」によってトリガーされる必要がありました。このオブジェクトでは、Springのキャッシング抽象化を介してGemFireに接続する新しいアプリケーションクライアントと古いアプリケーションクライアントが混在していました。たとえば、アプリケーションドメインオブジェクトフィールドは、アプリの新しいバージョンで変更されます。
とにかく、これがあなたにもっと多くのアイデアを助けたり与えたりすることを願っています。
乾杯!