首页 > 数据库 >Redis动态热点数据缓存策略设计

Redis动态热点数据缓存策略设计

时间:2025-01-16 16:30:22浏览次数:3  
标签:缓存 Redis value private key 动态 public redisTemplate

Redis动态热点数据缓存策略设计

1. 热点数据识别机制

1.1 计数器方式

@Service
public class HotDataCounter {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // 访问计数
    public void incrementCounter(String key) {
        String countKey = "counter:" + key;
        redisTemplate.opsForValue().increment(countKey, 1);
        // 设置计数器过期时间,比如1小时
        redisTemplate.expire(countKey, 1, TimeUnit.HOURS);
    }

    // 获取访问次数
    public Long getCounter(String key) {
        String countKey = "counter:" + key;
        return (Long) redisTemplate.opsForValue().get(countKey);
    }
}

1.2 LRU算法实现

public class LRUCache<K, V> extends LinkedHashMap<K, V> {
    private final int capacity;

    public LRUCache(int capacity) {
        super(capacity, 0.75f, true);
        this.capacity = capacity;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > capacity;
    }
}

2. 动态缓存策略实现

2.1 基础缓存服务

@Service
public class DynamicCacheService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private HotDataCounter hotDataCounter;
    // 热点阈值
    private static final long HOT_THRESHOLD = 100;

    // 获取数据
    public Object getData(String key) {
        // 增加访问计数
        hotDataCounter.incrementCounter(key);
        // 从缓存获取数据
        Object value = redisTemplate.opsForValue().get(key);
        if (value != null) {
            return value;
        }
        // 从数据库获取数据
        value = getFromDB(key);
        // 判断是否为热点数据
        if (isHotData(key)) {
            // 热点数据设置较长的过期时间
            redisTemplate.opsForValue().set(key, value, 1, TimeUnit.HOURS);
        } else {
            // 非热点数据设置较短的过期时间
            redisTemplate.opsForValue().set(key, value, 5, TimeUnit.MINUTES);
        }
        return value;
    }

    // 判断是否为热点数据
    private boolean isHotData(String key) {
        Long count = hotDataCounter.getCounter(key);
        return count != null && count > HOT_THRESHOLD;
    }
}

2.2 定时任务更新策略

@Component
public class HotDataScheduler {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Scheduled(fixedRate = 300000) // 每5分钟执行一次
    public void updateHotData() {
        // 获取所有计数器
        Set<String> counterKeys = redisTemplate.keys("counter:");
        if (counterKeys == null) return;
        // 更新热点数据过期时间
        for (String counterKey : counterKeys) {
            String dataKey = counterKey.substring("counter:".length());
            Long count = (Long) redisTemplate.opsForValue().get(counterKey);
            if (count != null && count > HOT_THRESHOLD) {
                // 延长热点数据过期时间
                redisTemplate.expire(dataKey, 1, TimeUnit.HOURS);
            }
        }
    }
}

3. 多级缓存策略

3.1 本地缓存配合Redis

@Service
public class MultiLevelCache {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    // 本地缓存
    private final LoadingCache<String, Object> localCache = CacheBuilder.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(5, TimeUnit.MINUTES)
            .build(new CacheLoader<String, Object>() {
                @Override
                public Object load(String key) {
                    return getFromRedis(key);
                }
            });

    public Object get(String key) {
        try {
            return localCache.get(key);
        } catch (ExecutionException e) {
            return getFromRedis(key);
        }
    }

    private Object getFromRedis(String key) {
        Object value = redisTemplate.opsForValue().get(key);
        if (value == null) {
            value = getFromDB(key);
            if (value != null) {
                redisTemplate.opsForValue().set(key, value);
            }
        }
        return value;
    }
}

4. 热点数据预加载

4.1 预热服务

@Service
public class HotDataPreloader {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @PostConstruct
    public void preloadHotData() {
        // 从统计数据中获取历史热点数据
        List<String> historicalHotKeys = getHistoricalHotKeys();
        // 预加载数据到Redis
        for (String key : historicalHotKeys) {
            Object value = getFromDB(key);
            if (value != null) {
                redisTemplate.opsForValue().set(key, value, 1, TimeUnit.HOURS);
            }
        }
    }
}

5. 缓存更新策略

5.1 更新服务

@Service
public class CacheUpdateService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // 更新缓存数据
    @Transactional
    public void updateData(String key, Object value) {
        // 更新数据库
        updateDB(key, value);
        // 判断是否为热点数据
        if (isHotData(key)) {
            // 直接更新缓存
            redisTemplate.opsForValue().set(key, value, 1, TimeUnit.HOURS);
        } else {
            // 删除缓存
            redisTemplate.delete(key);
        }
    }
}

6. 监控和告警

6.1 监控服务

@Service
public class CacheMonitorService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // 监控缓存命中率
    public double getHitRate() {
        Long hits = (Long) redisTemplate.opsForValue().get("cache:hits");
        Long misses = (Long) redisTemplate.opsForValue().get("cache:misses");
        if (hits == null || misses == null) {
            return 0.0;
        }
        return (double) hits / (hits + misses);
    }

    // 记录缓存访问
    public void recordAccess(boolean isHit) {
        String key = isHit ? "cache:hits" : "cache:misses";
        redisTemplate.opsForValue().increment(key, 1);
    }
}

7. 配置管理

7.1 动态配置

@Configuration
@RefreshScope
public class CacheConfig {
    @Value("${cache.hot.threshold:100}")
    private long hotThreshold;
    @Value("${cache.hot.expire:3600}")
    private long hotExpireSeconds;
    @Value("${cache.normal.expire:300}")
    private long normalExpireSeconds;

}

8. 总结

  1. 热点识别

    • 使用计数器记录访问频率
    • 实现LRU算法管理缓存
  2. 动态缓存

    • 根据访问频率动态调整过期时间
    • 定时任务更新热点数据
  3. 多级缓存

    • 本地缓存配合Redis
    • 减少网络开销
  4. 预加载机制

    • 系统启动时预加载历史热点数据
    • 提高系统启动后的访问性能
  5. 更新策略

    • 热点数据直接更新缓存
    • 非热点数据采用删除策略
  6. 监控告警

    • 监控缓存命中率
    • 记录访问统计
  7. 配置管理

    • 支持动态调整配置
    • 灵活控制缓存策略

标签:缓存,Redis,value,private,key,动态,public,redisTemplate
From: https://blog.csdn.net/nmsoftklb/article/details/145118731

相关文章

  • Java程序运行时动态生成日志文件-loj4j
    1.创建Appender;2.logger实例和appender的绑定和解绑3.logger实例使用privatestaticfinalLoggerLOGGER=LogManager.getLogger(DeviceManagerCuppsIOHandler.class);创建<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-a......
  • vue2动态给标签绑定属性
    <el-table-columnlabel="保司提交资料报文"prop="insuranceSubmitData"show-overflow-tooltip/>将show-overflow-tooltip改为动态绑定此处是为了将表格渲染封装成通用组件<templatev-for="iteminarr"><templatev-if="item.t......
  • 深入探索Vue.js 3中基于Composition API的动态组件开发
    在前端开发中,组件是构建用户界面的基础,而Vue.js作为一种流行的前端框架,也提供了灵活强大的组件机制。在本文中,我们将深入探索基于Vue.js3的CompositionAPI,开发一个动态组件加载的技术方案。这项技术对于那些需要高可维护性和按需加载的应用来说尤其重要。什么是动态组件加......
  • SpringBoot+Redis+消息队列 技术的抢购方案【附有图文+示例代码】
    文章目录SpringBoot+Redis+消息队列技术的抢购方案13.1简单抢购13.2模拟高并下发抢购jmeter工具使用实现13.3数据安全问题加锁synchronized分布式锁13.4消息队列完成抢购【yml配置文件】【实体类】【redis工具类】【队列配置类】【controller】【队列监听器RabbitQM......
  • Nacos: 一个动态服务发现与配置管理平台
    Nacos:一个动态服务发现与配置管理平台引言在微服务架构日益普及的今天,服务之间的调用和配置管理变得越来越复杂。为了简化这一过程并提高开发效率,阿里巴巴推出了Nacos——一个易于使用的动态服务发现、配置管理和服务管理平台。Nacos是什么?Nacos(DynamicNamingandCo......
  • vue3.0 keep-alive 缓存指定页面
    vue3.0keep-alive缓存指定页面**vue2.0和vue3.0keep-alive写法是有区别,不要太过于依赖AI**!!!!vue2的写法(不适用于vue3)<keep-alive><router-viewv-if="$route.meta.keepAlive"></router-view></keep-alive><router-viewv-if="!$route.met......
  • 如何开启主机上的MongoDB和Redis服务?
    关于您提到的如何开启主机上的MongoDB和Redis服务的问题,我们将为您提供详细的解决方案。MongoDB和Redis是两种广泛使用的NoSQL数据库,分别用于存储结构化数据和缓存数据。确保这些服务正常运行对于提升网站性能至关重要。以下是针对这两种服务的具体操作步骤。开启MongoDB服务......
  • Caffeine 缓存 动态的为每个值设置过期时间
    引入jar<!--本地缓存caffeine--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency&......
  • Redis安装配置与使用
    Redis是什么Redis(RemoteDictionaryServer)是一个开源的内存数据库,遵守BSD协议,它提供了一个高性能的键值(key-value)存储系统,常用于缓存、消息队列、会话存储等应用场景。它的优点很多,Redis与其他key-value存储系统的主要区别在于其提供了丰富的数据类型、高性能的读写能力、......
  • 初步使用动态web项目实现增删改查
    我目前使用的工具是eclipse(2024-12),并且没用使用maven这类工具,数据库使用的是MySQL,服务器为tomcat10.1。在编码并实现增删改查操作前,要进行一些准备工作。首先在file里创建一个动态web项目(DymamicWebProject),我们连接数据库要提前连接驱动与一个包,需要右键这个文件,选择构建路径,......