• 简易的redis分布式锁 RedisLockUtil


    实现的诉求,多台服务器上,执行相同的方法,一次只能执行一个,如果多个请求了执行方法,那么排队等待执行。

    方案:采用三方服务redis的key做唯一标识控制。超时后。

    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.util.StringUtils;
    
    import com.ccjr.commons.utils.SpringUtils;
    
    import lombok.extern.slf4j.Slf4j;
    
    
    /**
     * @desc REDIS分布式锁工具类
     * @author 陈惟鲜 chenweixian
     * @date 2020年8月19日 下午4:20:46
     *
     */
    @Slf4j
    public class RedisLockUtil {
        
        @SuppressWarnings("unchecked")
        private static RedisTemplate<String, Object> redisTemplate = (RedisTemplate<String, Object>) SpringUtils.getBean("redisTemplate");
        
        private static long lockTimeout = 5*1000L; //锁定时间30s
    
        /**
         * 加锁
         *
         * @param key
         * @param value 当前时间+ 超时时间
         * @return
         */
        public static boolean lock(String key, long currvalue) {
            String value = currvalue+lockTimeout+"";
            //未加锁,则加锁
            if (redisTemplate.opsForValue().setIfAbsent(key, value)) {
                return true;
            }
            
            do {
                //获取锁解锁时间
                String currentValue = (String)redisTemplate.opsForValue().get(key);
                //如果锁过期
                if (!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()) {
                    //获得上一个锁的时间
                    String olcValue = (String)redisTemplate.opsForValue().getAndSet(key, value);
                    if (!StringUtils.isEmpty(olcValue) && olcValue.equals(currentValue)) {
                        return true;
                    }
                }
                try {
    //                log.info("等待500 ms key:{},value:{},cur:{}, 剩余:{}",key,value, System.currentTimeMillis(), Long.parseLong(value)-System.currentTimeMillis());
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                }
            }while(Long.parseLong(value) > System.currentTimeMillis());
    
            return false;
        }
    
        /**
         * 解锁
         *
         * @param key
         * @param value
         */
        public static void unlock(String key, long currvalue) {
            try {
                String value = currvalue+lockTimeout+"";
                String currentVlue = (String)redisTemplate.opsForValue().get(key);
                if (!StringUtils.isEmpty(currentVlue) && currentVlue.equals(value)) {
                    redisTemplate.opsForValue().getOperations().delete(key);
                }
            } catch (Exception e) {
                log.error("【redis分布式锁】 解锁异常" + e.getMessage(), e);
            }
        }
    }

    测试:

        @Test
        public void testRedisLock() {
            String key = "testRedisLock";
            for (int i=0;i<100;i++) {
                long currvalue = System.currentTimeMillis();
                try {
                    System.out.println(i + "A="+ RedisLockUtil.lock(key, currvalue));
    
                    System.out.println("做了些事情开始。。");
    //                try {
    //                    Thread.sleep(4000);
    //                } catch (InterruptedException e) {}
                    System.out.println("做了些事情结束。。");
                }
                finally {
                    currvalue = System.currentTimeMillis();
                    System.out.println(i + "B="+ RedisLockUtil.lock(key, currvalue));
                    RedisLockUtil.unlock(key, currvalue);
                    System.out.println(i + "C="+ RedisLockUtil.lock(key, currvalue));
                }
            }
        }
  • 相关阅读:
    iOS input disabled显示不清楚
    钉钉小程序——JSAPI
    留言板
    友链
    mysql---存储引擎
    union与limit
    spring--setter注入
    spring---生命周期
    sql03-连接查询
    sql01--认识表
  • 原文地址:https://www.cnblogs.com/a393060727/p/14303812.html
Copyright © 2020-2023  润新知