feat(iot): 优化保洁工单配置缓存服务
- 新增空值缓存机制,防止缓存穿透 - 新增区域+类型配置查询缓存 - 统一缓存 TTL 为 5 分钟,空值缓存 60 秒 - 新增缓存失效方法 evictAreaCache Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,8 @@ public class CleanOrderIntegrationConfigServiceImpl implements CleanOrderIntegra
|
||||
*/
|
||||
private static final String CONFIG_DEVICE_KEY_PATTERN = "iot:clean:config:device:%s";
|
||||
private static final String CONFIG_AREA_KEY_PATTERN = "iot:clean:config:area:%s";
|
||||
private static final String CONFIG_WRAPPER_KEY_PATTERN = "iot:clean:config:wrapper:%s";
|
||||
private static final String CONFIG_AREA_TYPE_KEY_PATTERN = "iot:clean:config:area:%s:type:%s";
|
||||
|
||||
/**
|
||||
* 配置缓存 TTL(秒)
|
||||
@@ -34,6 +36,11 @@ public class CleanOrderIntegrationConfigServiceImpl implements CleanOrderIntegra
|
||||
* 5 分钟自动过期
|
||||
*/
|
||||
private static final int CONFIG_CACHE_TTL_SECONDS = 300;
|
||||
|
||||
/**
|
||||
* 空值缓存标记(防止缓存穿透)
|
||||
*/
|
||||
private static final String NULL_CACHE_VALUE = "NULL";
|
||||
|
||||
@Resource
|
||||
private OpsAreaDeviceRelationMapper relationMapper;
|
||||
@@ -111,44 +118,106 @@ public class CleanOrderIntegrationConfigServiceImpl implements CleanOrderIntegra
|
||||
public AreaDeviceConfigWrapper getConfigByAreaIdAndRelationType(Long areaId, String relationType) {
|
||||
log.debug("[CleanOrderConfig] 查询单个区域配置:areaId={}, relationType={}", areaId, relationType);
|
||||
|
||||
// 1. 尝试从缓存读取
|
||||
String cacheKey = formatAreaTypeKey(areaId, relationType);
|
||||
String cachedValue = stringRedisTemplate.opsForValue().get(cacheKey);
|
||||
|
||||
if (cachedValue != null) {
|
||||
if (NULL_CACHE_VALUE.equals(cachedValue)) {
|
||||
log.debug("[CleanOrderConfig] 命中空值缓存:areaId={}, relationType={}", areaId, relationType);
|
||||
return null;
|
||||
}
|
||||
log.debug("[CleanOrderConfig] 命中区域类型缓存:areaId={}, relationType={}", areaId, relationType);
|
||||
return JsonUtils.parseObject(cachedValue, AreaDeviceConfigWrapper.class);
|
||||
}
|
||||
|
||||
// 2. 从数据库查询
|
||||
List<OpsAreaDeviceRelationDO> relations = relationMapper.selectListByAreaIdAndRelationType(areaId, relationType);
|
||||
|
||||
if (relations.isEmpty()) {
|
||||
// 缓存空值,防止缓存穿透
|
||||
stringRedisTemplate.opsForValue().set(cacheKey, NULL_CACHE_VALUE, 60, TimeUnit.SECONDS);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 返回第一个启用的配置
|
||||
return relations.stream()
|
||||
AreaDeviceConfigWrapper wrapper = relations.stream()
|
||||
.filter(r -> r.getEnabled())
|
||||
.findFirst()
|
||||
.map(this::wrapConfig)
|
||||
.orElse(null);
|
||||
|
||||
// 3. 写入缓存
|
||||
if (wrapper != null) {
|
||||
stringRedisTemplate.opsForValue().set(
|
||||
cacheKey,
|
||||
JsonUtils.toJsonString(wrapper),
|
||||
CONFIG_CACHE_TTL_SECONDS,
|
||||
TimeUnit.SECONDS
|
||||
);
|
||||
} else {
|
||||
// 缓存空值
|
||||
stringRedisTemplate.opsForValue().set(cacheKey, NULL_CACHE_VALUE, 60, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AreaDeviceConfigWrapper getConfigWrapperByDeviceId(Long deviceId) {
|
||||
log.debug("[CleanOrderConfig] 查询设备完整配置:deviceId={}", deviceId);
|
||||
|
||||
// 1. 尝试从缓存读取
|
||||
String cacheKey = formatWrapperKey(deviceId);
|
||||
String cachedValue = stringRedisTemplate.opsForValue().get(cacheKey);
|
||||
|
||||
if (cachedValue != null) {
|
||||
if (NULL_CACHE_VALUE.equals(cachedValue)) {
|
||||
log.debug("[CleanOrderConfig] 命中空值缓存:deviceId={}", deviceId);
|
||||
return null;
|
||||
}
|
||||
log.debug("[CleanOrderConfig] 命中 Wrapper 缓存:deviceId={}", deviceId);
|
||||
return JsonUtils.parseObject(cachedValue, AreaDeviceConfigWrapper.class);
|
||||
}
|
||||
|
||||
// 2. 从数据库查询
|
||||
OpsAreaDeviceRelationDO relation = relationMapper.selectByDeviceId(deviceId);
|
||||
|
||||
if (relation == null || !relation.getEnabled()) {
|
||||
// 缓存空值,防止缓存穿透(TTL 较短:60秒)
|
||||
stringRedisTemplate.opsForValue().set(cacheKey, NULL_CACHE_VALUE, 60, TimeUnit.SECONDS);
|
||||
return null;
|
||||
}
|
||||
|
||||
return wrapConfig(relation);
|
||||
AreaDeviceConfigWrapper wrapper = wrapConfig(relation);
|
||||
|
||||
// 3. 写入缓存
|
||||
stringRedisTemplate.opsForValue().set(
|
||||
cacheKey,
|
||||
JsonUtils.toJsonString(wrapper),
|
||||
CONFIG_CACHE_TTL_SECONDS,
|
||||
TimeUnit.SECONDS
|
||||
);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictCache(Long deviceId) {
|
||||
String cacheKey = formatDeviceKey(deviceId);
|
||||
stringRedisTemplate.delete(cacheKey);
|
||||
// 清除设备相关的所有缓存
|
||||
stringRedisTemplate.delete(formatDeviceKey(deviceId));
|
||||
stringRedisTemplate.delete(formatWrapperKey(deviceId));
|
||||
log.info("[CleanOrderConfig] 清除设备配置缓存:deviceId={}", deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictAreaCache(Long areaId) {
|
||||
String cacheKey = formatAreaKey(areaId);
|
||||
stringRedisTemplate.delete(cacheKey);
|
||||
// 清除区域相关的所有缓存(包括各类型)
|
||||
stringRedisTemplate.delete(formatAreaKey(areaId));
|
||||
// 清除常用类型缓存
|
||||
stringRedisTemplate.delete(formatAreaTypeKey(areaId, "TRAFFIC_COUNTER"));
|
||||
stringRedisTemplate.delete(formatAreaTypeKey(areaId, "BEACON"));
|
||||
stringRedisTemplate.delete(formatAreaTypeKey(areaId, "BADGE"));
|
||||
log.info("[CleanOrderConfig] 清除区域配置缓存:areaId={}", areaId);
|
||||
}
|
||||
|
||||
@@ -174,10 +243,24 @@ public class CleanOrderIntegrationConfigServiceImpl implements CleanOrderIntegra
|
||||
return String.format(CONFIG_DEVICE_KEY_PATTERN, deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化设备配置包装器缓存 Key
|
||||
*/
|
||||
private static String formatWrapperKey(Long deviceId) {
|
||||
return String.format(CONFIG_WRAPPER_KEY_PATTERN, deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化区域配置缓存 Key
|
||||
*/
|
||||
private static String formatAreaKey(Long areaId) {
|
||||
return String.format(CONFIG_AREA_KEY_PATTERN, areaId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化区域+类型配置缓存 Key
|
||||
*/
|
||||
private static String formatAreaTypeKey(Long areaId, String relationType) {
|
||||
return String.format(CONFIG_AREA_TYPE_KEY_PATTERN, areaId, relationType);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user