美文网首页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脚本了。

相关文章

  • 分布式锁

    Redis实现 使用Redis集群实现分布式锁。使用 Redisson 框架,基于LUA脚本去实现 Zookepp...

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

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

  • RedisTemplate使用lua脚本分布式锁

    Jedis进行分布式锁 我们使用 jedis 原生的对象执行lua脚本的话,非常简单,也很直观。但是真实的项目里,...

  • Redis应用

    1.分布式锁 RedissonLock分布式锁1)加锁是通过Lua脚本实现的,如果分布式锁不存在,则会通过hset...

  • 分布式锁之redis-lua脚本

    目录 redis分布式锁,Lua,Lua脚本,lua redis,redis lua 分布式锁,redis set...

  • Redis分布式锁的实战应用

    以商品超卖为例讲解Redis分布式锁 主要讲解Redis实现分布式锁的两种实现方式:Jedis实现、Redisso...

  • 使用redis实现分布式锁

    几种redis分布式锁实现 一、简单的分布式锁实现 利用下面的命令,实现一个带自动删除的分布式锁 编写两个lua脚...

  • RedisTemplate执行lua脚本抛出异常IllegalS

    基于Redis的分布式锁的释放过程,为了防止释放错误,需要使用lua脚本实现原子释放,但是RedisTemplat...

  • 以商品超卖为例讲解Redis分布式锁

    本案例主要讲解Redis实现分布式锁的两种实现方式:Jedis实现、Redisson实现。网上关于这方面讲解太多了...

  • 9. Redisson源码剖析-读写锁

    一、读锁 读写锁的意义: 1, redis分布式锁,主要就是在理解他里面的lua脚本的逻辑,逻辑全部都在lua脚本...

网友评论

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

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