Redis妙用之分布式锁

文章目录

成功的秘诀端赖坚毅的决心。—— 英狄兹雷利

问题原因:Redis是单线程的操作,在单线程的操作下不会产生问题,但是在多线程下,对Redis进行GET和SET操作,因为不是原子性操作,所以此时会产生问题。

实现思路:当一个线程对进行操作时,对其进行占位,此时其他线程进来,发现已经被其他线程占用,然后进行等待或放弃操作。

实现代码:

  • 使用线程池封装Jedis
public interface JedisCall {
    void call(Jedis jedis);
}

public class RedisDemo {

    private JedisPool jedisPool;

    public RedisDemo(){
        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
        //设置连接池最大空闲数
        config.setMaxIdle(100);
        //最大连接数
        config.setMaxTotal(300);
        //设置最大等待时间 -1表示无限制
        config.setMaxWaitMillis(30000);
        //开启空闲时间检查有效性
        config.setTestOnBorrow(true);
        //连接redis
        jedisPool = new JedisPool(config, "127.0.0.1", 6379, 30000);
    }

    public void execute(JedisCall jedisCall) {
    	//try resource
        try (Jedis jedis = jedisPool.getResource()) {
            jedisCall.call(jedis);
        }
    }
}

  • 因为有些时候业务操作的时间超过了锁的过期时间,所以需要解决锁超时问题。Lua 脚本可以在 Redis 服务端原子的执行多个 Redis 命令,同时Redis也内置了对Lua的支持,所以引入Lua脚本来解决锁超时的问题。

通过vi创建Lua脚本。

if redis.call("get",KEYS[1])==ARGV[1] then
   return redis.call("del",KEYS[1])
else return 0
end

执行命令,给Lua生成sha1校验和,之后调用sha1就可以调用脚本。

cat lua_lock.lua | redis-cli script load --pipe

在这里插入图片描述

public class JedisTest {

    public static void main(String[] args) {
        RedisDemo redisDemo = new RedisDemo();
            redisDemo.execute(jedis -> {
                //生成uuid作为释放锁标识符
                String uuid = UUID.randomUUID().toString();
                //设置key作为锁的标志 过期时间为10秒
                String key = jedis.set("k1", "v1", new SetParams().nx().ex(10));
                if (key != null && "OK".equals(key)){
                    //获取锁 成功业务操作
                    System.out.println("success" );
                    //执行Lua脚本 释放锁
                    jedis.evalsha("b8059ba43af6ffe8bed3db65bac35d452f8115d8", Arrays.asList("k1"), Arrays.asList(uuid));
                }else {
                    //未获取锁 失败业务操作
                     System.out.println("fail");
                }
            });
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值