您的位置:首页 > 数据库 > Redis

redis之双重检查锁(double check lock)的使用

2018-03-13 22:50 435 查看
通常使用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);@Autowiredprivate CacheService cacheService;public void testCache2() throws Exception{for (int i = 0; i < THREAD_NUM; i++) {new Thread(new QueryTask()).start();cdl.countDown();}//主线程休眠 也可以考虑用joinThread.currentThread().sleep(5000);//结果:并发导致缓存失效,使用策略 double check lock (SpringCache)}private class QueryTask implements Runnable{@Overridepublic 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 locksynchronized (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.查询Servicepublic List<Order> queryByTemplate(){return cacheTemplateService.findCache(CACHE_KEY, 10, TimeUnit.MINUTES,new TypeReference<List<Order>>() {}, new CacheLoadable<List<Order>>() {@Overridepublic List<Order> load() {return orderMapper.getAll();}});}3.封装成模板@Componentpublic class CacheTemplateService {@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate 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-3sops.set(key,JSON.toJSON(result),expire, timeUnit);return  result;}}}
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: