Redis实现原生分布式锁,客户端调用服务端的 Lua 脚本解决Redis原生分布式锁原子性问题

Redis实现原生分布式锁,客户端调用服务端的 Lua 脚本解决Redis原生分布式锁原子性问题

1. Jedis 封装 Redis

  • 添加依赖
		<dependency>
            <groupId>redis.clientsgroupId>
            <artifactId>jedisartifactId>
        dependency>
  • CallWithJedis
public interface CallWithJedis {
    void call(Jedis jedis);
}
  • Redis
public class Redis {

    private JedisPool jedisPool;

    public Redis() {
        GenericObjectPoolConfig<Jedis> config=new GenericObjectPoolConfig<>();
        config.setMaxTotal(100);
        config.setMinIdle(10);
        config.setMaxWaitMillis(10000);
        config.setMaxIdle(20);
        jedisPool = new JedisPool(config, "192.168.140.130",6379,5000,"123");
    }
    public void execute(CallWithJedis call){
        call.call(jedisPool.getResource());
    }
}


2.在服务端编写 Lua 脚本

  1. 进入redis安装目录
[root@localhost ~]# cd /opt/redis-6.2.6
[root@localhost redis-6.2.6]# mkdir lua
[root@localhost redis-6.2.6]# cd lua
[root@localhost lua]# vi lock.lua

  1. Lua 脚本内容
if reids.call("get",KEYS[1])==ARGV[1] then
   return redis.call("del",KEYS[1])
else
   return 0
end

  1. script load 这个命令会在 Redis 服务器中缓存 Lua 脚本,并返回脚本内容的 SHA1 校验和,然后在
    Java 端调用时,传入 SHA1 校验和作为参数,这样 Redis 服务端就知道执行哪个脚本了
[root@localhost redis-6.2.6]# src/redis-cli -a 123 -x script load < lua/lock.lua
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
"e7fffe24eb4a6e50ca3118cc1fbcddf32cfe9de0"
[root@localhost redis-6.2.6]# 

  1. 测试

public class PrimordialLock {
    public static void main(String[] args) {
        Redis redis = new Redis();
        for (int i=0;i<2;i++) {
            redis.execute(jedis -> {
                //先生成一个随机字符串
                String value = UUID.randomUUID().toString();
                //获取锁
                String set = jedis.set("k1",value , new SetParams().nx().ex(5));
                if (set != null && "OK".equals(set)) {
                    //给锁设置过期时间
                    jedis.set("age","18");
                    System.out.println("jedis.get(\"age\") = " + jedis.get("age"));
                    //调用 Redis 的 lua 脚本释放锁
                    jedis.evalsha("e7fffe24eb4a6e50ca3118cc1fbcddf32cfe9de0", Arrays.asList("k1"),Arrays.asList(value));
                } else {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("锁被占用");
                }
            });
        }
    }
}

Redis实现原生分布式锁,客户端调用服务端的 Lua 脚本解决Redis原生分布式锁原子性问题_第1张图片
Redis实现原生分布式锁,客户端调用服务端的 Lua 脚本解决Redis原生分布式锁原子性问题_第2张图片

你可能感兴趣的:(redis,spring,boot,redis,缓存)