美文网首页redis缓存实战探究专题
Jedis实现分布式锁与Lua脚本的实现

Jedis实现分布式锁与Lua脚本的实现

作者: 先生zeng | 来源:发表于2019-10-29 11:19 被阅读0次

    本篇文章主要讲解如何使用Jedis实现一个简略的分布式锁的,想了解分布式锁相关的内容可以看我这篇文章讲解的:
    https://www.jianshu.com/p/b3f95f2d146e

    下面直接撸代码:

    首先需要一个连接redis的初始化类

    package com.zxy.test.jedis.slock;
    
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    import redis.clients.jedis.JedisPoolConfig;
    
    import java.util.HashMap;
    
    /**
     * @description:...
     * @author xinyao.zeng
     * @date 2019/10/28
     * @version  1.0
     */
    public class JedisConnectionUtils {
    
    //    HashMap
        private static JedisPool pool = null;
    
        static {
            JedisPoolConfig poolConfig = new JedisPoolConfig();
    
            poolConfig.setMaxTotal(1000);
    
    
          //  pool = new JedisPool(poolConfig,"47.74.144.61",6379,500000);
            pool = new JedisPool(poolConfig,"192.168.88.139",6379);
    
        }
    
        public static Jedis getJedis(){
            return pool.getResource();
        }
    }
    

    一个获取锁和释放锁的工具类

    package com.zxy.test.jedis.slock;
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.Transaction;
    import java.util.UUID;
    
    /**
     * @description:...
     * @author xinyao.zeng
     * @date 2019/10/28
     * @version  1.0
     */
    public class DistributeLock {
    
        //获得锁
    
        public String acquireLock(String lockName,long acquireTimeout,long lockTimeout) {
    
            String identify = UUID.randomUUID().toString();
            String lockKey = "lock:" + lockName;
            int locExpire = (int) (lockTimeout / 1000);
            Jedis jedis = null;
            try{
               jedis = JedisConnectionUtils.getJedis();
    
                long end = System.currentTimeMillis() + acquireTimeout;
                while (System.currentTimeMillis() < end) {
    
                    //设置成功,代表获取锁成功
                    if (jedis.setnx(lockKey, identify) == 1) {
                        jedis.expire(lockKey, locExpire);  //设置超时时间
                        return identify;
                    }
    
                    if (jedis.ttl(lockKey) == -1) {
                        jedis.expire(lockKey, locExpire);
                    }
    
                    try {
                        //等待片刻进行获取锁的重试
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }finally{
                jedis.close();
            }
            return null;
        }
    
        //释放锁
        public boolean releaseLock(String lockName,String identifier){
            System.out.println(lockName+"开始释放锁:"+identifier);
            String lockKey = "lock:"+lockName;
            Jedis jedis = null;
            boolean isRelease = false;
    
            try {
                jedis = JedisConnectionUtils.getJedis();
                while (true) {
                    //监控,保证释放锁,不会被打断
                    jedis.watch(lockKey);
                    //判断是否为同一把锁
                    if (identifier.equals(jedis.get(lockKey))) {
                        //事务删除锁
                        Transaction transaction = jedis.multi();
    
                        transaction.del(lockKey);
    
                        if (transaction.exec().isEmpty()) {
                            continue;
                        }
                        //认为锁释放成功
                        isRelease = true;
    
                    }
                    //TODO 异常
                    jedis.unwatch();
                    break;
                }
    
            }finally {
                jedis.close();
            }
            return isRelease;
        }
    }
    

    测试类如下:

    public class Test extends Thread {
    
        @Override
        public void run() {
            while(true) {
                DistributeLock distributeLock = new DistributeLock();
                String lock = distributeLock.acquireLock("updateLock", 2000, 5000);
                if (lock != null) {
                    System.out.println(Thread.currentThread().getName() + "成功获得锁");
                    try {
                        Thread.sleep(1000);
    
                        boolean updateLock = distributeLock.releaseLock("updateLock", lock);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }
    
        public static void main(String[] args) {
    
            Test test = new Test();
            CountDownLatch countDownLatch = new CountDownLatch(1);
    
          /*  try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
            for(int i=0;i<10;i++){
                new Thread(test,"tName"+i).start();
            }
    //        countDownLatch.countDown();
    
        }
    }
    

    测试结果:


    lua脚本的使用

    在DistributeLock 类中添加该方法,在测试类中使用该方法获取锁。

     public boolean releaseLockWithLua(String lockName,String identifier){
            System.out.println(lockName+"开始释放锁:"+identifier);
    
            Jedis jedis=JedisConnectionUtils.getJedis();
            String lockKey="lock:"+lockName;
    
            String lua="if redis.call(\"get\",KEYS[1])==ARGV[1] then " +
                    "return redis.call(\"del\",KEYS[1]) " +
                    "else return 0 end";
            Long rs=(Long) jedis.eval(lua,1,new String[]{lockKey,identifier});
            if(rs.intValue()>0){
                return true;
            }
            return false;
    
        }
    

    测试类

    public class UnitTest extends Thread{
    
        @Override
        public void run() {
            while(true){
                DistributedLock distributedLock=new DistributedLock();
                String rs=distributedLock.acquireLock("updateOrder",
                        2000,5000);
                if(rs!=null){
                    System.out.println(Thread.currentThread().getName()+"-> 成功获得锁:"+rs);
                    try {
                        Thread.sleep(1000);
                        distributedLock.releaseLockWithLua("updateOrder",rs);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }
    
        public static void main(String[] args) {
            UnitTest unitTest=new UnitTest();
            for(int i=0;i<10;i++){
                new Thread(unitTest,"tName:"+i).start();
            }
        }
    }
    

    然后就可以执行lua脚本了。

    相关文章

      网友评论

        本文标题:Jedis实现分布式锁与Lua脚本的实现

        本文链接:https://www.haomeiwen.com/subject/btpwvctx.html