Jedis實現(xiàn)分布式鎖與Lua腳本的實現(xiàn)

本篇文章主要講解如何使用Jedis實現(xiàn)一個簡略的分布式鎖的,想了解分布式鎖相關(guān)的內(nèi)容可以看我這篇文章講解的:
http://www.itdecent.cn/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) {

                //設(shè)置成功,代表獲取鎖成功
                if (jedis.setnx(lockKey, identify) == 1) {
                    jedis.expire(lockKey, locExpire);  //設(shè)置超時時間
                    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) {
                //監(jiān)控,保證釋放鎖,不會被打斷
                jedis.watch(lockKey);
                //判斷是否為同一把鎖
                if (identifier.equals(jedis.get(lockKey))) {
                    //事務(wù)刪除鎖
                    Transaction transaction = jedis.multi();

                    transaction.del(lockKey);

                    if (transaction.exec().isEmpty()) {
                        continue;
                    }
                    //認(rèn)為鎖釋放成功
                    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();

    }
}

測試結(jié)果:


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();
        }
    }
}

然后就可以執(zhí)行l(wèi)ua腳本了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容