概述
通常使用redis的使用如下:
public List<Order> query(){ //1.查询缓存 ValueOperations ops = redisTemplate.opsForValue(); String json = String.valueOf(ops.get(CACHE_KEY)); //2.判断缓存中是否有数据 if(!StringUtils.isEmpty(json) || !json.equalsIgnoreCase("null")){ //返回缓存数据 logger.info("----query for cache----------"); return JSON.parseArray(json,Order.class); } //3.查看数据库,并且返回数据,同时更新缓存 List<Order> list = orderMapper.getAll(); ops.set(CACHE_KEY,JSON.toJSON(list),10, TimeUnit.MINUTES); return list; }
当使用多线程 CountDownLatch测试时,会造成缓存击穿
代码如下:
public class CacheTest2 { private static final Logger logger = LoggerFactory.getLogger(CacheTest2.class); private static final int THREAD_NUM = 10; //倒计时器 private CountDownLatch cdl = new CountDownLatch(THREAD_NUM); @Autowired private CacheService cacheService; public void testCache2() throws Exception{ for (int i = 0; i < THREAD_NUM; i++) { new Thread(new QueryTask()).start(); cdl.countDown(); } //主线程休眠 也可以考虑用join Thread.currentThread().sleep(5000); //结果:并发导致缓存失效,使用策略 double check lock (SpringCache) } private class QueryTask implements Runnable{ @Override public void run() { try { cdl.await(); } catch (InterruptedException e) { e.printStackTrace(); } List<Order> list = cacheService.query(); logger.info(list.toString()); } } }
使用双重检查锁:
public /*synchronized */List<Order> query(){ //1.查询缓存 ValueOperations ops = redisTemplate.opsForValue(); String json = String.valueOf(ops.get(CACHE_KEY)); //2.判断缓存中是否有数据 if(!StringUtils.isEmpty(json) || !json.equalsIgnoreCase("null")){ //返回缓存数据 logger.info("----query for cache----------"); return JSON.parseArray(json,Order.class); } //Spring Cache //double check lock synchronized (this){ json = String.valueOf(ops.get(CACHE_KEY)); if(!StringUtils.isEmpty(json) || !json.equalsIgnoreCase("null")){ //返回缓存数据 logger.info("----query for cache----------"); return JSON.parseArray(json,Order.class); } //3.查看数据库,并且返回数据,同时更新缓存 List<Order> list = orderMapper.getAll(); ops.set(CACHE_KEY,JSON.toJSON(list),10, TimeUnit.MINUTES); return list; } }
封装成redis缓存查询模板
1.查询接口
public interface CacheLoadable<T> { public T load(); }
2.查询Service
public List<Order> queryByTemplate(){ return cacheTemplateService.findCache(CACHE_KEY, 10, TimeUnit.MINUTES, new TypeReference<List<Order>>() { }, new CacheLoadable<List<Order>>() { @Override public List<Order> load() { return orderMapper.getAll(); } }); }
3.封装成模板
@Component public class CacheTemplateService { @Autowired private RedisTemplate redisTemplate; @Autowired private OrderMapper orderMapper; public static final Logger logger = LoggerFactory.getLogger(CacheTemplateService.class); public <T> T findCache(String key, long expire, TimeUnit timeUnit, TypeReference<T> clazz, CacheLoadable<T> cacheLoadable){ ValueOperations ops = redisTemplate.opsForValue(); String json = String.valueOf(ops.get(key)); if(!StringUtils.isEmpty(json) || !json.equalsIgnoreCase("null")){ //返回缓存数据 logger.info("----query for cache----------"); return JSON.parseObject(json,clazz); } synchronized (this){ json = String.valueOf(ops.get(key)); if(!StringUtils.isEmpty(json) || !json.equalsIgnoreCase("null")){ logger.info("----query for cache----------"); return JSON.parseObject(json,clazz); } //核心业务 T result = cacheLoadable.load(); //2-3s ops.set(key,JSON.toJSON(result),expire, timeUnit); return result; } } }
最后
以上就是传统毛衣为你收集整理的redis之双重检查锁(double check lock)的使用的全部内容,希望文章能够帮你解决redis之双重检查锁(double check lock)的使用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复