| 
                         Redis分布式锁实现的正确姿势的实现代码: 
- public interface DistributedLock { 
 -     /** 
 -      * 获取锁 
 -      * @author zhi.li 
 -      * @return 锁标识 
 -      */ 
 -     String acquire(); 
 -  
 -     /** 
 -      * 释放锁 
 -      * @author zhi.li 
 -      * @param indentifier 
 -      * @return 
 -      */ 
 -     boolean release(String indentifier); 
 - } 
 -  
 - /** 
 -  * @author zhi.li 
 -  * @Description 
 -  * @created 2019/1/1 20:32 
 -  */ 
 - @Slf4j 
 - public class RedisDistributedLock implements DistributedLock{ 
 -  
 -     private static final String LOCK_SUCCESS = "OK"; 
 -     private static final Long RELEASE_SUCCESS = 1L; 
 -     private static final String SET_IF_NOT_EXIST = "NX"; 
 -     private static final String SET_WITH_EXPIRE_TIME = "PX"; 
 -  
 -     /** 
 -      * redis 客户端 
 -      */ 
 -     private Jedis jedis; 
 -  
 -     /** 
 -      * 分布式锁的键值 
 -      */ 
 -     private String lockKey; 
 -  
 -     /** 
 -      * 锁的超时时间 10s 
 -      */ 
 -     int expireTime = 10 * 1000; 
 -  
 -     /** 
 -      * 锁等待,防止线程饥饿 
 -      */ 
 -     int acquireTimeout  = 1 * 1000; 
 -  
 -     /** 
 -      * 获取指定键值的锁 
 -      * @param jedis jedis Redis客户端 
 -      * @param lockKey 锁的键值 
 -      */ 
 -     public RedisDistributedLock(Jedis jedis, String lockKey) { 
 -         this.jedis = jedis; 
 -         this.lockKey = lockKey; 
 -     } 
 -  
 -     /** 
 -      * 获取指定键值的锁,同时设置获取锁超时时间 
 -      * @param jedis jedis Redis客户端 
 -      * @param lockKey 锁的键值 
 -      * @param acquireTimeout 获取锁超时时间 
 -      */ 
 -     public RedisDistributedLock(Jedis jedis,String lockKey, int acquireTimeout) { 
 -         this.jedis = jedis; 
 -         this.lockKey = lockKey; 
 -         this.acquireTimeout = acquireTimeout; 
 -     } 
 -  
 -     /** 
 -      * 获取指定键值的锁,同时设置获取锁超时时间和锁过期时间 
 -      * @param jedis jedis Redis客户端 
 -      * @param lockKey 锁的键值 
 -      * @param acquireTimeout 获取锁超时时间 
 -      * @param expireTime 锁失效时间 
 -      */ 
 -     public RedisDistributedLock(Jedis jedis, String lockKey, int acquireTimeout, int expireTime) { 
 -         this.jedis = jedis; 
 -         this.lockKey = lockKey; 
 -         this.acquireTimeout = acquireTimeout; 
 -         this.expireTime = expireTime; 
 -     } 
 -  
 -     @Override 
 -     public String acquire() { 
 -         try { 
 -             // 获取锁的超时时间,超过这个时间则放弃获取锁 
 -             long end = System.currentTimeMillis() + acquireTimeout; 
 -             // 随机生成一个value 
 -             String requireToken = UUID.randomUUID().toString(); 
 -             while (System.currentTimeMillis() < end) { 
 -                 String result = jedis.set(lockKey, requireToken, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); 
 -                 if (LOCK_SUCCESS.equals(result)) { 
 -                     return requireToken; 
 -                 } 
 -                 try { 
 -                     Thread.sleep(100); 
 -                 } catch (InterruptedException e) { 
 -                     Thread.currentThread().interrupt(); 
 -                 } 
 -             } 
 -         } catch (Exception e) { 
 -             log.error("acquire lock due to error", e); 
 -         } 
 -  
 -         return null; 
 -     } 
 -  
 -     @Override 
 -     public boolean release(String identify) { 
 -   if(identify == null){ 
 -             return false; 
 -         } 
 -  
 -         String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; 
 -         Object result = new Object(); 
 -         try { 
 -             result = jedis.eval(script, Collections.singletonList(lockKey), 
 -                 Collections.singletonList(identify)); 
 -         if (RELEASE_SUCCESS.equals(result)) { 
 -             log.info("release lock success, requestToken:{}", identify); 
 -             return true; 
 -         }}catch (Exception e){ 
 -             log.error("release lock due to error",e); 
 -         }finally { 
 -             if(jedis != null){ 
 -                 jedis.close(); 
 -             } 
 -         } 
 -  
 -         log.info("release lock failed, requestToken:{}, result:{}", identify, result); 
 -         return false; 
 -     } 
 - } 
 
  
下面就以秒杀库存数量为场景,测试下上面实现的分布式锁的效果。具体测试代码如下:- public class RedisDistributedLockTest { 
 -     static int n = 500; 
 -     public static void secskill() { 
 -         System.out.println(--n); 
 -     } 
 -  
 -     public static void main(String[] args) { 
 -         Runnable runnable = () -> { 
 -             RedisDistributedLock lock = null; 
 -             String unLockIdentify = null; 
 -             try { 
 -                 Jedis conn = new Jedis("127.0.0.1",6379); 
 -                 lock = new RedisDistributedLock(conn, "test1"); 
 -                 unLockIdentify = lock.acquire(); 
 -                 System.out.println(Thread.currentThread().getName() + "正在运行"); 
 -                 在此我向大家推荐一个架构学习交流圈:830478757 帮助突破瓶颈 提升思维能力 
 -                 secskill(); 
 -             } finally { 
 -                 if (lock != null) { 
 -                     lock.release(unLockIdentify); 
 -                 } 
 -             } 
 -         }; 
 -  
 -         for (int i = 0; i < 10; i++) { 
 -             Thread t = new Thread(runnable); 
 -             t.start(); 
 -         } 
 -     } 
 - } 
 
  
运行效果如下图所示。从图中可以看出,同一个资源在同一个时刻只能被一个线程获取,从而保证了库存数量N的递减是顺序的。 
五、总结                        (编辑:泰州站长网) 
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! 
                     |