WebFlux(Project Reactor)带参数方法的缓存实现需求问询
WebFlux带参数方法的TTL缓存与外部触发更新方案
一、基于Caffeine的带TTL参数缓存实现
生产环境推荐使用Caffeine(支持Reactor适配)实现带参数、TTL的缓存,它能自动处理过期和线程安全问题,比手动维护缓存逻辑更可靠。
1. 定义缓存实例
创建带有TTL的缓存,用参数组合作为唯一缓存键:
import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import reactor.core.publisher.Flux; import java.util.concurrent.TimeUnit; // 缓存键格式:"城市:年龄",值为缓存后的Flux<Customer> private final LoadingCache<String, Flux<Customer>> customerCache = Caffeine.newBuilder() .expireAfterWrite(30, TimeUnit.MINUTES) // 设置TTL为30分钟,可按需调整 .build(cacheKey -> { // 解析缓存键为原始参数 String[] params = cacheKey.split(":"); String city = params[0]; String age = params[1]; // 调用原业务方法并缓存Flux结果,避免重复订阅触发多次查询 return customerService.getCustomersByCityAndAge(city, age).cache(); });
2. 封装缓存查询方法
对外提供带参数的查询入口,自动复用缓存:
public Flux<Customer> getCachedCustomers(String city, String age) { String cacheKey = String.format("%s:%s", city, age); return customerCache.get(cacheKey); }
二、外部条件触发缓存更新
当收到队列消息等外部事件时,直接清除对应缓存键的旧数据,下次查询会自动加载最新结果;也可以主动刷新缓存。
1. 精准清除指定参数的缓存
如果消息携带具体的城市和年龄参数,直接清除对应键的缓存:
// 队列消息的监听处理方法示例 public void handleCustomerUpdate(String city, String age) { String cacheKey = String.format("%s:%s", city, age); // 移除缓存,下次查询会重新加载最新数据 customerCache.invalidate(cacheKey); // 若需要主动刷新(无需等待下次查询),可调用refresh方法(异步执行) // customerCache.refresh(cacheKey); }
2. 批量清除某类缓存
如果消息是某城市所有客户数据更新,可批量清除该城市相关的所有缓存键:
public void handleCityCustomerUpdate(String city) { String keyPrefix = String.format("%s:", city); // 遍历缓存键,清除所有以指定城市开头的缓存 customerCache.asMap().keySet().stream() .filter(key -> key.startsWith(keyPrefix)) .forEach(customerCache::invalidate); }
关键点说明
- 缓存键唯一性:必须基于方法的所有入参生成唯一键,确保不同参数组合对应独立缓存条目
- Flux缓存处理:调用
.cache()将业务方法返回的Flux转为可复用的缓存流,避免每次订阅都触发业务查询 - TTL可靠性:依赖Caffeine的成熟过期策略,无需手动维护过期时间和清理逻辑
内容的提问来源于stack exchange,提问作者obe6
相关产品推荐
相关产品推荐

