Tôi đã có cùng một vấn đề. Tôi đang phát triển một số dịch vụ dữ liệu dựa trên cơ sở dữ liệu, sử dụng Redis làm nơi lưu trữ bộ nhớ cache bằng cách sử dụng chú thích Spring Caching. Nếu máy chủ Redis không khả dụng, tôi muốn các dịch vụ tiếp tục hoạt động như thể chưa được xóa, thay vì đưa ra các ngoại lệ.
Lúc đầu, tôi đã thử một CacheErrorHandler tùy chỉnh, một cơ chế do Spring cung cấp. Nó không hoàn toàn hoạt động, vì nó chỉ xử lý RuntimeExceptions và vẫn cho phép những thứ như java.net.ConnectException làm nổ tung mọi thứ.
Cuối cùng những gì tôi đã làm là mở rộng RedisTemplate, ghi đè một vài phương thức execute () để chúng ghi lại các cảnh báo thay vì tuyên truyền các ngoại lệ. Nó có vẻ như là một sự tấn công và tôi có thể đã ghi đè quá ít phương thức execute () hoặc quá nhiều, nhưng nó hoạt động giống như một sự quyến rũ trong tất cả các trường hợp thử nghiệm của tôi.
Tuy nhiên, có một khía cạnh hoạt động quan trọng đối với cách tiếp cận này. Nếu máy chủ Redis không khả dụng, bạn phải xóa nó (xóa các mục nhập) trước khi làm cho nó khả dụng trở lại. Nếu không, bạn có thể bắt đầu truy xuất các mục nhập trong bộ nhớ cache có dữ liệu không chính xác do các bản cập nhật đã xảy ra trong thời gian chờ đợi.
Dưới đây là nguồn. Hãy sử dụng nó. Tôi hy vọng nó sẽ hữu ích.
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;
}
}
}