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 切所有接口 会简化很多 }

 

posted @ 2019-06-01 17:30  dikeboyR  阅读(195)  评论(0编辑  收藏  举报