开发者

Redis定时监控与数据处理的实践指南

目录
  • 1. 背景与需求分析
    • 1.1 原始需求
    • 1.2 新需求
  • 2. Redis 数据结构选型:Set vs. Hash
    • 3. 代码改造:从 Set 迁移到 Hash
      • 3.1 改造后的 LogMediaAdIdCachehttp://www.devze.com
      • 3.2 主要改进点
    • 4. 定时任务优化:每10秒监控 Redis 数据
      • 4.1 新增 LogStatsMonitorJob
      • 4.2 功能说明
    • 5. 完整代码实现
      • 5.1 LogMediaAdIdCache(改造后)
      • 5.2 LogStatsMonitorJob(新增)
      • 5.3 配置类(可选)
    • 6. 总结与最佳实践
      • 6.1 关键改进
      • 6.2 最佳实践
      • 6.3 后续优化方向
    • 结语

      1. 背景与需求分析

      1.1 原始需求

      我们有一个 LogMediaAdIdCache 类,用于缓存广告位 ID,并定期从 Redis 刷新数据。原始实现使用 Set 存储数据,结构如下:

      SET logscraping:mediaAdId [id1, id2, id3, ...]
      

      但随着业务发展,我们需要存储更多元信息(如广告位名称、状态、更新时间等),仅用 Set 已无法满足需求。

      1.2 新需求

      • 存储结构化数据:每个广告位 ID 需要关联额外信息(如 namestatusupdateTime)。
      • 高效查询:快速获取某个广告位的详细信息。
      • 定时监控:每10秒检查 Redis 数据变化,确保缓存一致性。

      因此,我们决定将数据结构从 Set 改为 Hash:

      HASH logscraping:mediaAdId
          id1 -> { "name": "广告位1", "status": "active" }
          id2 -> { "name": "广告位2", "status": "inactive" }
      

      2. Redis 数据结构选型:Set vs. Hash

      特性SetHash
      存储方式无序唯一集合键值对存储(field-value)
      适用场景去重、集合运算(交集、并集)结构化数据,需存储额外属性
      查询效率O(1) 判断元素是否存在O(1) 按 field 查询 value
      扩展性只能存储单一值可存储复杂对象(jsON、Map)

      结论:

      • 如果仅需存储 ID 并判断是否存在,Set 更高效。
      • 如果需要存储额外信息(如广告位详情),Hash 更合适。

      3. 代码改造:从 Set 迁移到 Hash

      3.1 改造后的 LogMediaAdIdCache

      @Component
      @Slf4j
      @RequiredArgsConstructor
      public class LogMediaAdIdCache {
          private final RedisTemplate<String, String> redisTemplate;
          private volatile Set<Long> cachedLogMediaAdIds = Collections.emptySet();
          public static final String LOG_REDIS_KEY = "logscraping:mediaAdId";
      
          @PostConstruct
          public void init() {
         javascript     refreshCache();
          }
      
          @Scheduled(fixedRate = 5 * 1000) // 每5秒刷新一次
          public void refreshCache() {
              try {
                  Map<Object, Object> idMap = redisTemplate.opsForHash().entries(LOG_REDIS_KEY);
                  if (idMap != null) {
                      Set<Long> newCache = idMap.keySet().stream()
                              .map(key -> Long.valueOf(key.toString()))
                              .collect(Collectors.toSet());
                      this.cachedLogMediaAdIds = newCache;
                      log.info("广告位ID缓存刷新成功,数量: {}", newCache.size());
                  }
              } catch (Exception e) {
                  log.error("刷新广告位ID缓存失败", e);
              }
          }
      
          public Set<Long> getLogMediaAdIds() {
              return Collections.unmodifiableSet(cachedLogMediaAdIds);
          }
      
          public boolean contains(Long mediaAdId) {
              return cachedLogMediaAdIds.contains(mediaAdId);
          }
      
          // 新增方法:获取广告位详情
          public String getAdInfo(Long mediaAdId) {
              return redisTemplate.<String, String>opsForHash().get(LOG_REDIS_KEY, mediaAdId.toString());
          }
      
          // 新增方法:更新广告位信息
          public void updateAdInfo(Long mediaAdId, String info) {
              redisTemplate.opsForHash().put(LOG_REDIS_KEY, mediaAdId.toString(), info);
              refreshCache(); // 立即刷新缓存
          }
      }
      

      3.2 主要改进点

      • 改用 opsForHash() 操作 Redis Hash,支持结构化存储。
      • 新增 getAdInfo() 方法,按广告位 ID 查询详情。
      • 新增 updateAdInfo() 方法,支持动态更新数据。

      4. 定时任务优化:每10秒监控 Redis 数据

      4.1 新增 LogStatsMonitorJob

      @Component
      @Slf4j
      @RequiredArgsConstructor
      public class LogStatsMonitorJob {
          private final RedisTemplate<String, String> redisTemplate;
          private static final String LOG_STATS_KEY = "log:stats:1635474646";
      
          @Scheduled(fixedRate = 10 * 1000) // 每10秒执行一次
          public void monitorLogStats() {
              String currentTimeKey = getFormattedTime();
              String fullKey = LOG_STATS_KEY + ":" + currentTimeKey;
      
              try {
                  Map<Object, Object> stats = redisTemplate.opsForHash().entries(fullKey);
                  if (stats == null || stats.isEmpty()) {
                      log.warn("未找到统计信息: {}", fullKey);
                      return;
                  }
      
                  log.info("----- 统计信息监控(Key: {})-----", fullKey);
                  stats.forEach((field, value) -> 
                      log.info("{}: {}", field, value));
      
                  // 业务处理示例
                 http://www.devze.com int total = Integer.parseInt(stats.getOrDefault("total", "0").toString());
                  if (total > 1000) {
                      log.warn("警告:数据量过大({}条)", total);
                  }
              } catch (Exception e) {
                  log.error("监控统计信息失败", e);
              }
          }
      
          private String getFormattedTime() {
              // 生成格式化的时间戳python,如 20250609175050
              return LocalDateTime.now()
                      .format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
          }
      }
      

      4.2 功能说明

      • 定时任务:每10秒检查 Redis Hash 数据。
      • 动态 Key:支持按时间戳生成 Key(如 log:stats:1635474646:20250609175js050)。
      • 异常处理:捕获 Redis 操作异常,避免任务中断。
      • 业务告警:数据量超过阈值时触发告警。

      5. 完整代码实现

      5.1 LogMediaAdIdCache(改造后)

      (见上文 3.1 节)

      5.2 LogStatsMonitorJob(新增)

      (见上文 4.1 节)

      5.3 配置类(可选)

      @Configuration
      @EnableScheduling
      public class SchedulingConfig {
          // 启用定时任务
      }
      

      6. 总结与最佳实践

      6.1 关键改进

      • 数据结构升级:从 Set → Hash,支持结构化存储。
      • 定时任务优化:每10秒监控数据,确保实时性。
      • 代码健壮性:异常处理 + 日志记录。

      6.2 最佳实践

      • 合理选择数据结构:根据业务场景选择 Set / Hash / ZSet 等。
      • 动态 Key 设计:如时间戳、业务ID等,方便数据分区。
      • 定时任务调优:
        • 短周期(如10s)适合实时监控。
        • 长周期(如1h)适合批量处理。
      • 异常处理:避免因 Redis 异常导致任务崩溃。

      6.3 后续优化方向

      • 数据分片:若数据量过大,可采用分片存储。
      • 分布式锁:避免多实例任务重复执行。
      • 数据过期策略:设置 TTL 自动清理旧数据。

      结语

      本文通过一个实际案例,演示了如何将 Redis 数据结构从 Set 迁移到 Hash,并实现高效定时监控。合理的数据结构选择 + 定时任务优化,可以显著提升系统性能和可维护性。

      以上就是Redis定时监控与数据处理实践指南的详细内容,更多关于Redis定时监控与数据处理的资料请关注编程客栈(www.devze.com)其它相关文章!

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新数据库

      数据库排行榜