123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- package com.bizmatics.service.util;
- import com.bizmatics.model.utils.TimeRangeParams;
- import com.bizmatics.model.utils.TimeRangeUtils;
- import com.github.benmanes.caffeine.cache.Cache;
- import com.github.benmanes.caffeine.cache.Caffeine;
- import com.bizmatics.persistence.mapper.HtAnalogDataMapper;
- import com.github.benmanes.caffeine.cache.stats.CacheStats;
- import lombok.RequiredArgsConstructor;
- import lombok.extern.slf4j.Slf4j;
- import lombok.var;
- import org.springframework.scheduling.annotation.Scheduled;
- import org.springframework.stereotype.Component;
- import java.math.BigDecimal;
- import java.util.List;
- import java.util.Map;
- import java.util.concurrent.TimeUnit;
- import java.util.stream.Collectors;
- /**
- *
- * @author fyc
- * @email yuchuan.fu@chinausky.com
- * @date 2025/8/28
- */
- @Slf4j
- @Component
- @RequiredArgsConstructor
- public class AnalogCache {
- private final HtAnalogDataMapper htAnalogDataMapper;
- /**
- * 本地缓存:expireAfterWrite = 60 秒
- */
- private final Cache<String, Map<String, BigDecimal>> cache =
- Caffeine.newBuilder()
- // 根据设备量自行调节
- .maximumSize(5_000)
- .expireAfterAccess(2, TimeUnit.MINUTES)
- .expireAfterWrite(5, TimeUnit.MINUTES)
- // 命中率监控
- .recordStats()
- .build();
- /**
- * 对外唯一入口
- */
- public Map<String, BigDecimal> get(String deviceCode,
- TimeRangeUtils.TimeRanges ranges) {
- String key = AggCacheKey.of(deviceCode, ranges).signature();
- // 如果 key 不存在,自动调用 loadFromDb
- return cache.get(key, k -> loadFromDb(deviceCode, ranges));
- }
- /**
- * 回源:真正查数据库
- */
- private Map<String, BigDecimal> loadFromDb(String deviceCode,
- TimeRangeUtils.TimeRanges ranges) {
- TimeRangeParams params = TimeRangeParams.builder()
- .deviceCode(deviceCode)
- .today(ranges.getToday())
- .monthStart(ranges.getMonthRange()[0])
- .monthEnd(ranges.getMonthRange()[1])
- .yearStart(ranges.getYearRange()[0])
- .yearEnd(ranges.getYearRange()[1])
- .yesterday(ranges.getYesterdayRange()[0])
- .lastMonthStart(ranges.getLastMonthRange()[0])
- .lastMonthEnd(ranges.getLastMonthRange()[1])
- .lastYearStart(ranges.getLastYearRange()[0])
- .lastYearEnd(ranges.getLastYearRange()[1])
- .sameDayStart(ranges.getSameDayRange()[0])
- .sameDayEnd(ranges.getSameDayRange()[1])
- .sameMonthStart(ranges.getSameMonthRange()[0])
- .sameMonthEnd(ranges.getSameMonthRange()[1])
- .sameYearStart(ranges.getSameYearRange()[0])
- .sameYearEnd(ranges.getSameYearRange()[1])
- .lastYearSameDayStart(ranges.getLastYearSameDay()[0])
- .lastYearSameDayEnd(ranges.getLastYearSameDay()[1])
- .lastYearSameMonthStart(ranges.getLastYearSameMonth()[0])
- .lastYearSameMonthEnd(ranges.getLastYearSameMonth()[1])
- .build();
- List<Map<String, Object>> rows = htAnalogDataMapper.aggregateAll(params);
- return rows.stream()
- .collect(Collectors.toMap(
- r -> (String) r.get("type"),
- r -> new BigDecimal(r.get("value").toString())
- ));
- }
- /* ---------------- 命中率日志(可选) ---------------- */
- @Scheduled(fixedDelay = 30_000)
- public void logCacheStats() {
- CacheStats stats = cache.stats();
- long size = cache.estimatedSize();
- // 预先格式化数字
- String hitRateFormatted = String.format("%.2f", stats.hitRate() * 100);
- String avgLoadTimeFormatted = String.format("%.2f", stats.averageLoadPenalty() / 1_000_000.0);
- log.info("缓存统计 - 大小: {}, 命中率: {}%, 加载次数: {}, 加载失败: {}, 平均加载时间: {}ms",
- size,
- hitRateFormatted,
- stats.loadCount(),
- stats.loadFailureCount(),
- avgLoadTimeFormatted);
- }
- }
|