Jag hade precis samma problem. Jag utvecklar några datatjänster mot en databas, och använder Redis som cachelagret i form av Spring Caching-kommentarer. Om Redis-servern blir otillgänglig vill jag att tjänsterna ska fortsätta att fungera som om de inte är cachade, snarare än att skapa undantag.
Först provade jag en anpassad CacheErrorHandler, en mekanism från Spring. Det fungerade inte riktigt, eftersom det bara hanterar RuntimeExceptions, och fortfarande låter saker som java.net.ConnectException spränga saker.
I slutändan vad jag gjorde var att utöka RedisTemplate, åsidosätta några execute()-metoder så att de loggar varningar istället för att sprida undantag. Det verkar vara lite av ett hack, och jag kan ha åsidosatt för få execute()-metoder eller för många, men det fungerar som en charm i alla mina testfall.
Det finns dock en viktig operativ aspekt av detta tillvägagångssätt. Om Redis-servern blir otillgänglig måste du spola den (rensa ur posterna) innan du gör den tillgänglig igen. Annars finns det en chans att du kan börja hämta cache-poster som har felaktiga data på grund av uppdateringar som inträffade under tiden.
Nedan finns källan. Använd den gärna. Jag hoppas att det hjälper.
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.serializer.RedisSerializer;
/**
* An extension of RedisTemplate that logs exceptions instead of letting them propagate.
* If the Redis server is unavailable, cache operations are always a "miss" and data is fetched from the database.
*/
public class LoggingRedisTemplate<K, V> extends RedisTemplate<K, V> {
private static final Logger logger = LoggerFactory.getLogger(LoggingRedisTemplate.class);
@Override
public <T> T execute(final RedisCallback<T> action, final boolean exposeConnection, final boolean pipeline) {
try {
return super.execute(action, exposeConnection, pipeline);
}
catch(final Throwable t) {
logger.warn("Error executing cache operation: {}", t.getMessage());
return null;
}
}
@Override
public <T> T execute(final RedisScript<T> script, final List<K> keys, final Object... args) {
try {
return super.execute(script, keys, args);
}
catch(final Throwable t) {
logger.warn("Error executing cache operation: {}", t.getMessage());
return null;
}
}
@Override
public <T> T execute(final RedisScript<T> script, final RedisSerializer<?> argsSerializer, final RedisSerializer<T> resultSerializer, final List<K> keys, final Object... args) {
try {
return super.execute(script, argsSerializer, resultSerializer, keys, args);
}
catch(final Throwable t) {
logger.warn("Error executing cache operation: {}", t.getMessage());
return null;
}
}
@Override
public <T> T execute(final SessionCallback<T> session) {
try {
return super.execute(session);
}
catch(final Throwable t) {
logger.warn("Error executing cache operation: {}", t.getMessage());
return null;
}
}
}