From 6c330764ea3bd3bdd2df9aa280b1222bf416f8e3 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Thu, 5 Feb 2026 00:58:14 +0800 Subject: [PATCH] =?UTF-8?q?refactor(statistics):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E7=BB=9F=E8=AE=A1=E6=BC=8F=E6=96=97=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E7=9A=84Redis=E7=BC=93=E5=AD=98=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除固定的Redis缓存key,改为包含日期维度的动态key - 修复日期范围检查逻辑中的时间顺序问题 - 统一多处相同的日期范围条件判断代码 - 移除实时模式下的数据持久化操作以避免缓存污染 --- .../mobile/impl/AppStatisticsServiceImpl.java | 19 +++++++------------ .../com/ycwl/basic/task/ScenicStatsTask.java | 11 +++++++---- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/ycwl/basic/service/mobile/impl/AppStatisticsServiceImpl.java b/src/main/java/com/ycwl/basic/service/mobile/impl/AppStatisticsServiceImpl.java index b2390fab..a4ae4a8d 100644 --- a/src/main/java/com/ycwl/basic/service/mobile/impl/AppStatisticsServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/mobile/impl/AppStatisticsServiceImpl.java @@ -145,7 +145,6 @@ public class AppStatisticsServiceImpl implements AppStatisticsService { @Override public ApiResponse userConversionFunnel(CommonQueryReq query) { - String redisKey = "statistics:tmp_cache:"+query.getScenicId(); AppStatisticsFunnelVO vo = new AppStatisticsFunnelVO(); if(query.getEndTime()==null && query.getStartTime()==null){ // 没有传时间,则代表用户没有自定义查询时间,使用standard来判断查询时间范围 @@ -156,8 +155,12 @@ public class AppStatisticsServiceImpl implements AppStatisticsService { //获取当前周期的具体时间范围 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 (!(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 list = statisticsMapper.listStatByScenic(query.getScenicId(), query.getStartTime(), query.getEndTime()); AppStatisticsFunnelVO resp = new AppStatisticsFunnelVO(); @@ -189,7 +192,7 @@ public class AppStatisticsServiceImpl implements AppStatisticsService { } } 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)) { String s = redisTemplate.opsForValue().get(redisKey); @@ -203,7 +206,7 @@ public class AppStatisticsServiceImpl implements AppStatisticsService { try { // 缓存 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)) { String s = redisTemplate.opsForValue().get(redisKey); @@ -270,14 +273,6 @@ public class AppStatisticsServiceImpl implements AppStatisticsService { vo.setPayOfOrderAmount(payOfOrderAmount.setScale(2, RoundingMode.HALF_UP)); vo.setRefundOfOrderNum(refundOfOrderNum); 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); } finally { lock.unlock(); diff --git a/src/main/java/com/ycwl/basic/task/ScenicStatsTask.java b/src/main/java/com/ycwl/basic/task/ScenicStatsTask.java index c20584f9..88db088c 100644 --- a/src/main/java/com/ycwl/basic/task/ScenicStatsTask.java +++ b/src/main/java/com/ycwl/basic/task/ScenicStatsTask.java @@ -93,8 +93,8 @@ public class ScenicStatsTask { // 写入数据库(REPLACE INTO 会自动更新已存在的记录) statisticsMapper.insertStat(scenicId, startTime, data); - // 删除该景区的缓存,确保下次查询时获取最新数据 - invalidateStatisticsCache(scenicId); + // 删除该景区该日期的缓存,确保下次查询时获取最新数据 + invalidateStatisticsCache(scenicId, startTime); } catch (Exception e) { log.error("统计景区 {} 在日期 {} 的数据时发生错误", scenic.getId(), DateUtil.formatDate(startTime), e); } @@ -109,9 +109,12 @@ public class ScenicStatsTask { /** * 删除景区统计缓存 * @param scenicId 景区ID + * @param date 统计日期 */ - private void invalidateStatisticsCache(Long scenicId) { - String redisKey = "statistics:tmp_cache:" + scenicId; + private void invalidateStatisticsCache(Long scenicId, Date date) { + String redisKey = String.format("statistics:tmp_cache:%s:%s", + scenicId, + DateUtil.formatDate(date)); redisTemplate.delete(redisKey); } }