Redis 分布式锁
public Object lock(String cacheKey,Type type) { Object cacheValue= getCacheValue(cacheKey,type); if(cacheValue!=null) { return cacheValue; }//如果已存在缓存,则直接取 String lockKey ="lock_"+cacheKey; boolean success = lettuceTemplate.opsForValue().setIfAbsent(lockKey, "1",20,TimeUnit.SECONDS);//seIfAbsent,如果不存在则设置,返回,true,否则false,这里设置了20秒过期时间,为了避免死锁 try { while(!success) { cacheValue= getCacheValue(cacheKey,type); if(cacheValue!=null) { lettuceTemplate.delete(lockKey); return cacheValue; } success = lettuceTemplate.opsForValue().setIfAbsent(lockKey, "1",20,TimeUnit.SECONDS); Thread.sleep(50); //每隔50秒,判断缓存数据是否存在,存在则直接返回,并且主动删除锁key } if(success) { cacheValue= getCacheValue(cacheKey,type); if(cacheValue!=null) { lettuceTemplate.delete(lockKey); return cacheValue; } return null; } //lockKey释放,说明已经存在缓存,直接取 } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; }
Type 的话是gson的类型,为了实体跟String相互转换,cahekey对应的缓存key
public Object getCacheValue(String key,Type type) { if(isCache) { String value = lettuceTemplate.opsForValue().get(key); if(value!=null) { return gson.fromJson(value, type); } } return null; } public void putCacheValue(String key, Object value,int cacheTime) { if(value!=null&&isCache) { if(cacheTime==0) { lettuceTemplate.opsForValue().set(key, gson.toJson(value));; } else { lettuceTemplate.opsForValue().set(key, gson.toJson(value),cacheTime,TimeUnit.SECONDS); } } }
调用的地方
public ResponseEntity getTypes() { String cacheKey = getCacheKey("type"); Type type = new TypeToken <List<TypeEntity>> () { }.getType(); Object cacheValue = lock(cacheKey, type); if(cacheValue==null) { List<TypeEntity> lists =mRomManager.getTypes(); putCacheValue(cacheKey,lists,0); return new ResponseEntity(lists); } else { return new ResponseEntity(cacheValue); }
//调用的地方, 因为有些缓存需要根据分页做不同的策略,如果简单的话用AOP 切所有接口 会简化很多 }