谷歌网站建设网站seo什么意思
在项目开发中,经常会用到缓存的操作,为了灵活性和可控性,好多项目都会自己封装redisUtil,这就导致Spring系列缓存注解@Cacheable、@CacheEvit、@CachePut、@CacheRemove等JSR-107系列注解用到的不多。
用redisUtil来缓存数据的场景大多类似,为了让逻辑更清晰,减少代码的冗余,提高方法的复用性,我特地封装了一个基于spring项目的小工具:
/*** 缓存工具*/
@Component
@Slf4j
public class CacheDataUtil {@Resourceprivate RedisService redisService;/*** 取缓存数据,缓存没有就查数据然后存入缓存** @param function 函数* @param param 入参* @param key 缓存key* @param <T> 入参类型* @param <R> 出参类型* @param timeOut 超时时间* @param timeUnit 超时时间单位* @return 数据*/public <T, R> R getData(Function<T, R> function, T param, String key, Integer timeOut, TimeUnit timeUnit) {// 从缓存读数据R cache = redisService.getCacheObject(key);// 有直接返回if (ObjectUtil.isNotEmpty(cache)) {log.info("返回缓存数据");return cache;}// 没有就去查R data = function.apply(param);// 查完写入缓存// List等情况,调用失败如果返回的是空列表,会写缓存,这样会从缓存查到数据,就不会走下边更新查询成功的数据到缓存的流程了if (null != data) {redisService.setCacheObject(key, data, timeOut, timeUnit);}return data;}}
该方法把要缓存数据的方法改成了function形式,作为了方法的入参。如有其他定制化需求,在此工具类里新写方法就好了,一个简单的缓存工具就完成了。
因为涉及的操作缓存,缓存属于共享资源,所以理论上该方法会有并发的问题,要不要处理,要根据需求的情况定,如果需求接受缓存有效期内数据的不更新,那完全没问题。至于要不要加锁等处理并发问题,我的观点是,数据强一致和性能不可兼顾,加锁会影响性能,反而丢掉了使用缓存的优势,如果要求强一致,使用缓存并不是一个完美的解决方案,如果能接受数据不一致问题,该方法可以满足需求,如果要提高数据一致性,可以把方法改进为延时双删。
该工具类提供了一个封装缓存操作的思路,更多的场景及需求,就需要在此思路上继续扩展了。