You've already forked FrameTour-BE
refactor(statistics): 重构应用统计漏斗服务的Redis缓存逻辑
- 移除固定的Redis缓存key,改为包含日期维度的动态key - 修复日期范围检查逻辑中的时间顺序问题 - 统一多处相同的日期范围条件判断代码 - 移除实时模式下的数据持久化操作以避免缓存污染
This commit is contained in:
@@ -145,7 +145,6 @@ public class AppStatisticsServiceImpl implements AppStatisticsService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiResponse<AppStatisticsFunnelVO> userConversionFunnel(CommonQueryReq query) {
|
public ApiResponse<AppStatisticsFunnelVO> userConversionFunnel(CommonQueryReq query) {
|
||||||
String redisKey = "statistics:tmp_cache:"+query.getScenicId();
|
|
||||||
AppStatisticsFunnelVO vo = new AppStatisticsFunnelVO();
|
AppStatisticsFunnelVO vo = new AppStatisticsFunnelVO();
|
||||||
if(query.getEndTime()==null && query.getStartTime()==null){
|
if(query.getEndTime()==null && query.getStartTime()==null){
|
||||||
// 没有传时间,则代表用户没有自定义查询时间,使用standard来判断查询时间范围
|
// 没有传时间,则代表用户没有自定义查询时间,使用standard来判断查询时间范围
|
||||||
@@ -156,8 +155,12 @@ public class AppStatisticsServiceImpl implements AppStatisticsService {
|
|||||||
//获取当前周期的具体时间范围
|
//获取当前周期的具体时间范围
|
||||||
standardToNewSpecificTime(query);
|
standardToNewSpecificTime(query);
|
||||||
}
|
}
|
||||||
|
// 构建包含日期维度的 Redis 缓存 key
|
||||||
|
String redisKey = String.format("statistics:tmp_cache:%s:%s",
|
||||||
|
query.getScenicId(),
|
||||||
|
query.getStartTime() != null ? DateUtil.formatDate(query.getStartTime()) : "null");
|
||||||
if (!query.isRealtime()) {
|
if (!query.isRealtime()) {
|
||||||
if (!(DateUtil.isIn(query.getStartTime(), DateUtil.tomorrow(), DateUtil.yesterday()) && DateUtil.isIn(query.getEndTime(), DateUtil.tomorrow(), DateUtil.yesterday()))) {
|
if (!(DateUtil.isIn(query.getStartTime(), DateUtil.yesterday(), DateUtil.tomorrow()) && DateUtil.isIn(query.getEndTime(), DateUtil.yesterday(), DateUtil.tomorrow()))) {
|
||||||
// 查询缓存数据
|
// 查询缓存数据
|
||||||
List<AppStatisticsFunnelVO> list = statisticsMapper.listStatByScenic(query.getScenicId(), query.getStartTime(), query.getEndTime());
|
List<AppStatisticsFunnelVO> list = statisticsMapper.listStatByScenic(query.getScenicId(), query.getStartTime(), query.getEndTime());
|
||||||
AppStatisticsFunnelVO resp = new AppStatisticsFunnelVO();
|
AppStatisticsFunnelVO resp = new AppStatisticsFunnelVO();
|
||||||
@@ -189,7 +192,7 @@ public class AppStatisticsServiceImpl implements AppStatisticsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!query.isRealtime()) {
|
if (!query.isRealtime()) {
|
||||||
if (DateUtil.isIn(query.getStartTime(), DateUtil.tomorrow(), DateUtil.yesterday()) && DateUtil.isIn(query.getEndTime(), DateUtil.tomorrow(), DateUtil.yesterday())) {
|
if (DateUtil.isIn(query.getStartTime(), DateUtil.yesterday(), DateUtil.tomorrow()) && DateUtil.isIn(query.getEndTime(), DateUtil.yesterday(), DateUtil.tomorrow())) {
|
||||||
// 缓存
|
// 缓存
|
||||||
if (redisTemplate.hasKey(redisKey)) {
|
if (redisTemplate.hasKey(redisKey)) {
|
||||||
String s = redisTemplate.opsForValue().get(redisKey);
|
String s = redisTemplate.opsForValue().get(redisKey);
|
||||||
@@ -203,7 +206,7 @@ public class AppStatisticsServiceImpl implements AppStatisticsService {
|
|||||||
try {
|
try {
|
||||||
// 缓存
|
// 缓存
|
||||||
if (!query.isRealtime()) {
|
if (!query.isRealtime()) {
|
||||||
if (DateUtil.isIn(query.getStartTime(), DateUtil.tomorrow(), DateUtil.yesterday()) && DateUtil.isIn(query.getEndTime(), DateUtil.tomorrow(), DateUtil.yesterday())) {
|
if (DateUtil.isIn(query.getStartTime(), DateUtil.yesterday(), DateUtil.tomorrow()) && DateUtil.isIn(query.getEndTime(), DateUtil.yesterday(), DateUtil.tomorrow())) {
|
||||||
// 缓存
|
// 缓存
|
||||||
if (redisTemplate.hasKey(redisKey)) {
|
if (redisTemplate.hasKey(redisKey)) {
|
||||||
String s = redisTemplate.opsForValue().get(redisKey);
|
String s = redisTemplate.opsForValue().get(redisKey);
|
||||||
@@ -270,14 +273,6 @@ public class AppStatisticsServiceImpl implements AppStatisticsService {
|
|||||||
vo.setPayOfOrderAmount(payOfOrderAmount.setScale(2, RoundingMode.HALF_UP));
|
vo.setPayOfOrderAmount(payOfOrderAmount.setScale(2, RoundingMode.HALF_UP));
|
||||||
vo.setRefundOfOrderNum(refundOfOrderNum);
|
vo.setRefundOfOrderNum(refundOfOrderNum);
|
||||||
vo.setRefundOfOrderAmount(refundOfOrderAmount.setScale(2, RoundingMode.HALF_UP));
|
vo.setRefundOfOrderAmount(refundOfOrderAmount.setScale(2, RoundingMode.HALF_UP));
|
||||||
// 仅在非 realtime 模式下写入缓存
|
|
||||||
// realtime=true 时由调用方(如定时任务)自行控制写入目标日期,不污染当天缓存
|
|
||||||
if (!query.isRealtime()) {
|
|
||||||
if (query.getScenicId() != null) {
|
|
||||||
statisticsMapper.insertStat(query.getScenicId(), new Date(), vo);
|
|
||||||
}
|
|
||||||
redisTemplate.opsForValue().set(redisKey, JacksonUtil.toJSONString(vo), 60, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
return ApiResponse.success(vo);
|
return ApiResponse.success(vo);
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ public class ScenicStatsTask {
|
|||||||
// 写入数据库(REPLACE INTO 会自动更新已存在的记录)
|
// 写入数据库(REPLACE INTO 会自动更新已存在的记录)
|
||||||
statisticsMapper.insertStat(scenicId, startTime, data);
|
statisticsMapper.insertStat(scenicId, startTime, data);
|
||||||
|
|
||||||
// 删除该景区的缓存,确保下次查询时获取最新数据
|
// 删除该景区该日期的缓存,确保下次查询时获取最新数据
|
||||||
invalidateStatisticsCache(scenicId);
|
invalidateStatisticsCache(scenicId, startTime);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("统计景区 {} 在日期 {} 的数据时发生错误", scenic.getId(), DateUtil.formatDate(startTime), e);
|
log.error("统计景区 {} 在日期 {} 的数据时发生错误", scenic.getId(), DateUtil.formatDate(startTime), e);
|
||||||
}
|
}
|
||||||
@@ -109,9 +109,12 @@ public class ScenicStatsTask {
|
|||||||
/**
|
/**
|
||||||
* 删除景区统计缓存
|
* 删除景区统计缓存
|
||||||
* @param scenicId 景区ID
|
* @param scenicId 景区ID
|
||||||
|
* @param date 统计日期
|
||||||
*/
|
*/
|
||||||
private void invalidateStatisticsCache(Long scenicId) {
|
private void invalidateStatisticsCache(Long scenicId, Date date) {
|
||||||
String redisKey = "statistics:tmp_cache:" + scenicId;
|
String redisKey = String.format("statistics:tmp_cache:%s:%s",
|
||||||
|
scenicId,
|
||||||
|
DateUtil.formatDate(date));
|
||||||
redisTemplate.delete(redisKey);
|
redisTemplate.delete(redisKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user