Commit d36e0479 authored by daniel's avatar daniel

fix(cache): 数据更新时同步清除缓存,缓存key统一使用常量定义

parent 1e18f002
...@@ -2,10 +2,12 @@ package com.dlbridge.jadp.common.cache; ...@@ -2,10 +2,12 @@ package com.dlbridge.jadp.common.cache;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations; import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Supplier; import java.util.function.Supplier;
...@@ -39,13 +41,24 @@ public class CacheTemplate { ...@@ -39,13 +41,24 @@ public class CacheTemplate {
@Resource @Resource
private ValueOperations<String, Object> valueOperations; private ValueOperations<String, Object> valueOperations;
@Resource
private RedisTemplate<String, Object> redisTemplate;
/** 各命名空间对应的本地 Guava 缓存,按需创建 */ /** 各命名空间对应的本地 Guava 缓存,按需创建 */
private final ConcurrentHashMap<String, Cache<String, Object>> localCaches = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, Cache<String, Object>> localCaches = new ConcurrentHashMap<>();
/** 默认本地缓存最大容量 */ /** 默认本地缓存最大容量 */
private static final int DEFAULT_LOCAL_MAX_SIZE = 1000; private static final int DEFAULT_LOCAL_MAX_SIZE = 1000;
/** Redis key 统一前缀 */ /** Redis key 统一前缀 */
private static final String REDIS_KEY_PREFIX = "gk:"; public static final String REDIS_KEY_PREFIX = "gk:";
// ===== 缓存命名空间常量 =====
public static final String NS_CMPT_INFO = "cmpt:info";
public static final String NS_CMPT_CUSTOMER = "cmpt:customer";
public static final String NS_CMPT_FUNC = "cmpt:func";
public static final String NS_CMPT_PARTNER = "cmpt:partner";
public static final String NS_CMPT_LIST_RESP = "cmpt:list:resp";
public static final String NS_CMPT_LIST_COUNT = "cmpt:list:count";
/** /**
* 两级缓存查询(自动降级:L1 → L2 → L3) * 两级缓存查询(自动降级:L1 → L2 → L3)
...@@ -115,6 +128,17 @@ public class CacheTemplate { ...@@ -115,6 +128,17 @@ public class CacheTemplate {
} }
} }
/**
* 按前缀批量清除 Redis 缓存 + 对应命名空间的本地缓存
*/
public void evictByPrefix(String namespace) {
evictLocal(namespace);
Set<String> keys = redisTemplate.keys(REDIS_KEY_PREFIX + namespace + ":*");
if (keys != null && !keys.isEmpty()) {
redisTemplate.delete(keys);
}
}
/** /**
* 按需创建本地缓存实例 * 按需创建本地缓存实例
*/ */
......
...@@ -191,7 +191,7 @@ public class CmptService { ...@@ -191,7 +191,7 @@ public class CmptService {
public Page<List<Cmpt>> queryCmpt(Pageable page, Map<String, String> param) { public Page<List<Cmpt>> queryCmpt(Pageable page, Map<String, String> param) {
// 响应级缓存:同一筛选条件+分页 的所有用户看到相同结果,缓存1分钟 // 响应级缓存:同一筛选条件+分页 的所有用户看到相同结果,缓存1分钟
// 1000 req/s 下,60秒窗口内每个缓存key仅查DB一次,DB压力降至 < 0.02 req/s // 1000 req/s 下,60秒窗口内每个缓存key仅查DB一次,DB压力降至 < 0.02 req/s
String responseCacheKey = "cmpt:list:resp:" + param.get("userId") + ":" + param.get("type") String responseCacheKey = CacheTemplate.REDIS_KEY_PREFIX + CacheTemplate.NS_CMPT_LIST_RESP + ":" + param.get("userId") + ":" + param.get("type")
+ ":" + param.get("keyword") + ":" + param.get("partnerId") + ":" + param.get("keyword") + ":" + param.get("partnerId")
+ ":" + page.getPageNumber() + ":" + page.getPageSize(); + ":" + page.getPageNumber() + ":" + page.getPageSize();
Object cached = valueOperations.get(responseCacheKey); Object cached = valueOperations.get(responseCacheKey);
...@@ -207,7 +207,7 @@ public class CmptService { ...@@ -207,7 +207,7 @@ public class CmptService {
} }
// count 短时缓存:同一筛选条件翻页时避免重复执行跨库COUNT查询 // count 短时缓存:同一筛选条件翻页时避免重复执行跨库COUNT查询
String countCacheKey = "cmpt:list:count:" + param.get("userId") + ":" + param.get("type") + ":" + param.get("keyword") + ":" + param.get("partnerId"); String countCacheKey = CacheTemplate.REDIS_KEY_PREFIX + CacheTemplate.NS_CMPT_LIST_COUNT + ":" + param.get("userId") + ":" + param.get("type") + ":" + param.get("keyword") + ":" + param.get("partnerId");
Long count = null; Long count = null;
Object cachedCount = valueOperations.get(countCacheKey); Object cachedCount = valueOperations.get(countCacheKey);
if (cachedCount != null) { if (cachedCount != null) {
...@@ -351,7 +351,7 @@ public class CmptService { ...@@ -351,7 +351,7 @@ public class CmptService {
public Partner getPartnerById(String parnter) { public Partner getPartnerById(String parnter) {
return cacheTemplate.get( return cacheTemplate.get(
"cmpt:partner", CacheTemplate.NS_CMPT_PARTNER,
parnter, parnter,
Partner.class, Partner.class,
5L, TimeUnit.MINUTES, 5L, TimeUnit.MINUTES,
......
package com.dlbridge.jadp.plugins.cmpt.web; package com.dlbridge.jadp.plugins.cmpt.web;
import com.dlbridge.jadp.common.cache.CacheTemplate;
import com.dlbridge.jadp.common.interceptor.PageView; import com.dlbridge.jadp.common.interceptor.PageView;
import com.dlbridge.jadp.common.persistence.IStorageService; import com.dlbridge.jadp.common.persistence.IStorageService;
import com.dlbridge.jadp.common.persistence.Result; import com.dlbridge.jadp.common.persistence.Result;
...@@ -50,6 +51,9 @@ public class CmptController { ...@@ -50,6 +51,9 @@ public class CmptController {
@Resource @Resource
private CmptSettingService cmptSettingService; private CmptSettingService cmptSettingService;
@Resource
private CacheTemplate cacheTemplate;
@Value("${server.url}") @Value("${server.url}")
private String serverURL; private String serverURL;
@Value("${timer.url}") @Value("${timer.url}")
...@@ -239,6 +243,11 @@ public class CmptController { ...@@ -239,6 +243,11 @@ public class CmptController {
cmptService.save(cmpt); cmptService.save(cmpt);
} else { } else {
cmptService.update(cmpt); cmptService.update(cmpt);
cacheTemplate.evict(CacheTemplate.NS_CMPT_INFO, String.valueOf(cmpt.getCmptId()));
cacheTemplate.evict(CacheTemplate.NS_CMPT_CUSTOMER, String.valueOf(cmpt.getCmptId()));
cacheTemplate.evict(CacheTemplate.NS_CMPT_FUNC, String.valueOf(cmpt.getCmptId()));
cacheTemplate.evictByPrefix(CacheTemplate.NS_CMPT_LIST_RESP);
cacheTemplate.evictByPrefix(CacheTemplate.NS_CMPT_LIST_COUNT);
} }
return com.neusoft.www.utils.web.Result.success().setContent(cmpt); return com.neusoft.www.utils.web.Result.success().setContent(cmpt);
......
...@@ -2,6 +2,7 @@ package com.dlbridge.jadp.plugins.cmpt.web; ...@@ -2,6 +2,7 @@ package com.dlbridge.jadp.plugins.cmpt.web;
import com.dlbridge.feign.GeexekScoreService; import com.dlbridge.feign.GeexekScoreService;
import com.dlbridge.feign.bean.News; import com.dlbridge.feign.bean.News;
import com.dlbridge.jadp.common.cache.CacheTemplate;
import com.dlbridge.jadp.common.interceptor.PageView; import com.dlbridge.jadp.common.interceptor.PageView;
import com.dlbridge.jadp.plugins.cmpt.bean.CmptSettingTemplate; import com.dlbridge.jadp.plugins.cmpt.bean.CmptSettingTemplate;
import com.dlbridge.jadp.plugins.cmpt.bean.FuncSetting; import com.dlbridge.jadp.plugins.cmpt.bean.FuncSetting;
...@@ -61,6 +62,9 @@ public class CmptSettingController { ...@@ -61,6 +62,9 @@ public class CmptSettingController {
@Resource @Resource
private GeexekScoreService geexekScoreService; private GeexekScoreService geexekScoreService;
@Resource
private CacheTemplate cacheTemplate;
/** /**
* 去功能管理页面 * 去功能管理页面
* *
...@@ -155,6 +159,9 @@ public class CmptSettingController { ...@@ -155,6 +159,9 @@ public class CmptSettingController {
count = cmptSettingService.updateByType(cmptSetting); count = cmptSettingService.updateByType(cmptSetting);
} }
if (count > 0) { if (count > 0) {
if (cmptSetting.getCmptId() != null) {
cacheTemplate.evict(CacheTemplate.NS_CMPT_FUNC, cmptSetting.getCmptId());
}
return new Result().setCode(200).setMsg("更新成功!"); return new Result().setCode(200).setMsg("更新成功!");
}else{ }else{
return new Result().setCode(-1).setMsg("更新失败!"); return new Result().setCode(-1).setMsg("更新失败!");
...@@ -166,6 +173,7 @@ public class CmptSettingController { ...@@ -166,6 +173,7 @@ public class CmptSettingController {
@ResponseBody @ResponseBody
public Result updateSettingOrder(String ids) { public Result updateSettingOrder(String ids) {
cmptSettingService.updateSettingOrder(ids); cmptSettingService.updateSettingOrder(ids);
cacheTemplate.evictByPrefix(CacheTemplate.NS_CMPT_FUNC);
return Result.success(); return Result.success();
} }
......
package com.dlbridge.jadp.plugins.cmpt.web; package com.dlbridge.jadp.plugins.cmpt.web;
import com.dlbridge.jadp.common.cache.CacheTemplate;
import com.dlbridge.jadp.plugins.cmpt.bean.Customer; import com.dlbridge.jadp.plugins.cmpt.bean.Customer;
import com.dlbridge.jadp.plugins.cmpt.dao.model.Cmpt; import com.dlbridge.jadp.plugins.cmpt.dao.model.Cmpt;
import com.dlbridge.jadp.plugins.cmpt.service.CmptService; import com.dlbridge.jadp.plugins.cmpt.service.CmptService;
...@@ -25,6 +26,9 @@ public class CustomerController { ...@@ -25,6 +26,9 @@ public class CustomerController {
@Resource @Resource
CustomerService customerService; CustomerService customerService;
@Resource
private CacheTemplate cacheTemplate;
@RequestMapping("index/{cmptId}") @RequestMapping("index/{cmptId}")
public ModelAndView saveOrUpdate(@PathVariable("cmptId") Integer cmptId, ModelAndView mv){ public ModelAndView saveOrUpdate(@PathVariable("cmptId") Integer cmptId, ModelAndView mv){
Cmpt cmpt = cmptService.queryCmptBycmptId(cmptId); Cmpt cmpt = cmptService.queryCmptBycmptId(cmptId);
...@@ -44,6 +48,7 @@ public class CustomerController { ...@@ -44,6 +48,7 @@ public class CustomerController {
@ResponseBody @ResponseBody
public Result saveOrUpdate(Customer customer){ public Result saveOrUpdate(Customer customer){
customerService.saveOrUpdate(customer); customerService.saveOrUpdate(customer);
cacheTemplate.evict(CacheTemplate.NS_CMPT_CUSTOMER, String.valueOf(customer.getCmptId()));
log.info("变更客服电话:"+customer); log.info("变更客服电话:"+customer);
return Result.success().setContent(customer); return Result.success().setContent(customer);
} }
......
...@@ -418,12 +418,12 @@ public class MicroApiController { ...@@ -418,12 +418,12 @@ public class MicroApiController {
@ApiOperation(value = "赛事", notes = "赛事", tags = {"首页接口"}) @ApiOperation(value = "赛事", notes = "赛事", tags = {"首页接口"})
public Result getCmpt(@PathVariable("cmptId") Integer cmptId) { public Result getCmpt(@PathVariable("cmptId") Integer cmptId) {
Cmpt cmpt = cacheTemplate.get( Cmpt cmpt = cacheTemplate.get(
"cmpt:info", // 缓存命名空间 CacheTemplate.NS_CMPT_INFO,
String.valueOf(cmptId), // 缓存键 String.valueOf(cmptId),
Cmpt.class, // 返回值类型 Cmpt.class,
2L, TimeUnit.MINUTES, // L1 本地缓存 TTL 2L, TimeUnit.MINUTES,
5L, TimeUnit.MINUTES, // L2 Redis 缓存 TTL 5L, TimeUnit.MINUTES,
() -> cmptService.queryCmptBycmptId(cmptId) // L3 数据库回调 () -> cmptService.queryCmptBycmptId(cmptId)
); );
return Result.success().setContent(cmpt); return Result.success().setContent(cmpt);
} }
...@@ -434,7 +434,7 @@ public class MicroApiController { ...@@ -434,7 +434,7 @@ public class MicroApiController {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Result getCustomer(@PathVariable("cmptId") Integer cmptId) { public Result getCustomer(@PathVariable("cmptId") Integer cmptId) {
Map<String, String> result = cacheTemplate.get( Map<String, String> result = cacheTemplate.get(
"cmpt:customer", CacheTemplate.NS_CMPT_CUSTOMER,
String.valueOf(cmptId), String.valueOf(cmptId),
Map.class, Map.class,
2L, TimeUnit.MINUTES, 2L, TimeUnit.MINUTES,
...@@ -513,7 +513,7 @@ public class MicroApiController { ...@@ -513,7 +513,7 @@ public class MicroApiController {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Result<List<Func>> func(@PathVariable("cmptId") int cmpId, HttpServletRequest request) { public Result<List<Func>> func(@PathVariable("cmptId") int cmpId, HttpServletRequest request) {
List<Func> list = cacheTemplate.get( List<Func> list = cacheTemplate.get(
"cmpt:func", CacheTemplate.NS_CMPT_FUNC,
String.valueOf(cmpId), String.valueOf(cmpId),
List.class, List.class,
2L, TimeUnit.MINUTES, 2L, TimeUnit.MINUTES,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment