You've already forked FrameTour-BE
feat(integration): 优化降级缓存策略,支持优先使用1分钟内缓存
- 新增优先缓存判断逻辑,1分钟内的缓存优先返回 - 调整默认缓存TTL常量命名以避免混淆 - 重构缓存读取流程,优先解析已读取的缓存值 - 提取缓存值解析方法,增强代码复用性 - 完善缓存存储与读取的日志记录 - 修复缓存TTL单位使用不一致的问题
This commit is contained in:
@@ -25,7 +25,8 @@ public class IntegrationFallbackService {
|
||||
|
||||
// 默认降级缓存配置
|
||||
private static final String DEFAULT_FALLBACK_PREFIX = "integration:fallback:";
|
||||
private static final long DEFAULT_FALLBACK_TTL = 7; // 7天
|
||||
private static final long DEFAULT_FALLBACK_TTL_DAYS = 1; // 7天
|
||||
private static final long FALLBACK_CACHE_PREFERRED_MAX_AGE_SECONDS = 60; // 1分钟
|
||||
|
||||
/**
|
||||
* 执行操作,失败时降级到缓存结果
|
||||
@@ -38,6 +39,24 @@ public class IntegrationFallbackService {
|
||||
* @return 操作结果或缓存的结果
|
||||
*/
|
||||
public <T> T executeWithFallback(String serviceName, String cacheKey, Supplier<T> operation, Class<T> resultClass) {
|
||||
String fullKey = buildFullCacheKey(serviceName, cacheKey);
|
||||
String cachedValue = null;
|
||||
boolean isPreferredCache = false;
|
||||
try {
|
||||
cachedValue = redisTemplate.opsForValue().get(fullKey);
|
||||
isPreferredCache = cachedValue != null && isFallbackCachePreferred(serviceName, fullKey);
|
||||
} catch (Exception e) {
|
||||
log.warn("[{}] 读取降级缓存失败,将继续尝试远端获取, cacheKey: {}", serviceName, cacheKey, e);
|
||||
}
|
||||
|
||||
if (isPreferredCache) {
|
||||
T preferredCacheResult = parseFallbackCacheValue(serviceName, cacheKey, cachedValue, resultClass);
|
||||
if (preferredCacheResult != null) {
|
||||
log.debug("[{}] 命中优先缓存(<=1分钟),直接返回, cacheKey: {}", serviceName, cacheKey);
|
||||
return preferredCacheResult;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
T result = operation.get();
|
||||
if (result != null) {
|
||||
@@ -47,7 +66,10 @@ public class IntegrationFallbackService {
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.warn("[{}] 操作失败,尝试降级到缓存结果, cacheKey: {}", serviceName, cacheKey, e);
|
||||
T fallbackResult = getFallbackFromCache(serviceName, cacheKey, resultClass);
|
||||
T fallbackResult = parseFallbackCacheValue(serviceName, cacheKey, cachedValue, resultClass);
|
||||
if (fallbackResult == null) {
|
||||
fallbackResult = getFallbackFromCache(serviceName, cacheKey, resultClass);
|
||||
}
|
||||
if (fallbackResult == null) {
|
||||
log.error("[{}] 操作失败且无缓存数据, cacheKey: {}", serviceName, cacheKey);
|
||||
throw e;
|
||||
@@ -88,8 +110,8 @@ public class IntegrationFallbackService {
|
||||
try {
|
||||
String fullKey = buildFullCacheKey(serviceName, cacheKey);
|
||||
String jsonValue = JacksonUtil.toJSONString(value);
|
||||
long ttl = getFallbackTtl(serviceName);
|
||||
redisTemplate.opsForValue().set(fullKey, jsonValue, ttl, TimeUnit.DAYS);
|
||||
long ttlDays = getFallbackTtl(serviceName);
|
||||
redisTemplate.opsForValue().set(fullKey, jsonValue, ttlDays, TimeUnit.DAYS);
|
||||
log.debug("[{}] 存储降级缓存成功, key: {}", serviceName, fullKey);
|
||||
} catch (Exception e) {
|
||||
log.warn("[{}] 存储降级缓存失败, cacheKey: {}", serviceName, cacheKey, e);
|
||||
@@ -116,6 +138,46 @@ public class IntegrationFallbackService {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前降级缓存是否应该优先使用。
|
||||
* 规则:缓存写入后的 1 分钟内优先使用,超过 1 分钟则优先尝试远端;远端失败再降级到缓存。
|
||||
*/
|
||||
private boolean isFallbackCachePreferred(String serviceName, String fullKey) {
|
||||
try {
|
||||
Long remainingSeconds = redisTemplate.getExpire(fullKey, TimeUnit.SECONDS);
|
||||
if (remainingSeconds == null || remainingSeconds < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long ttlDays = getFallbackTtl(serviceName);
|
||||
long expectedTtlSeconds = TimeUnit.DAYS.toSeconds(ttlDays);
|
||||
if (remainingSeconds > expectedTtlSeconds) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long ageSeconds = expectedTtlSeconds - remainingSeconds;
|
||||
return ageSeconds <= FALLBACK_CACHE_PREFERRED_MAX_AGE_SECONDS;
|
||||
} catch (Exception e) {
|
||||
log.warn("[{}] 判断降级缓存有效期失败,视为不优先, key: {}", serviceName, fullKey, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T parseFallbackCacheValue(String serviceName, String cacheKey, String cachedValue, Class<T> resultClass) {
|
||||
if (cachedValue == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
if (resultClass == String.class) {
|
||||
return resultClass.cast(cachedValue);
|
||||
}
|
||||
return JacksonUtil.parseObject(cachedValue, resultClass);
|
||||
} catch (Exception e) {
|
||||
log.warn("[{}] 解析降级缓存失败, cacheKey: {}", serviceName, cacheKey, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除降级缓存
|
||||
*
|
||||
@@ -204,7 +266,7 @@ public class IntegrationFallbackService {
|
||||
*/
|
||||
private long getFallbackTtl(String serviceName) {
|
||||
if (!integrationProperties.getFallback().isEnabled()) {
|
||||
return DEFAULT_FALLBACK_TTL;
|
||||
return DEFAULT_FALLBACK_TTL_DAYS;
|
||||
}
|
||||
|
||||
// 获取服务特定的TTL
|
||||
|
||||
Reference in New Issue
Block a user