Redis Lua同步锁实现源码解析

 更新时间:2023年05月18日 10:43:23   作者:多喝灬丶烫水  
这篇文章主要为大家介绍了Redis Lua同步锁实现源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

Redis+Lua同步锁

Jedis配置

@Configuration
@Getter
@Setter
@Slf4j
@ConfigurationProperties(prefix = "jedis")
public class JedisConfig {
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.password}")
    private String password;
    private int timeout;
    private int maxTotal;
    private int maxIdle;
    private int minIdle;
    @Bean
    public JedisPool jedisPool() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);
        jedisPoolConfig.setMaxTotal(maxTotal);
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);
        log.info("JedisPool连接成功:" + host + "\t" + port);
        return jedisPool;
    }
}

Jedis工具类→获取jedis

@Component
public class JedisUtil {
    @Resource
    private JedisPool jedisPool;
    /**
     * 获取Jedis资源
     */
    public Jedis getJedis() {
        return jedisPool.getResource();
    }
    /**
     * 释放Jedis连接
     */
    public void close(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }
}

redis 锁工具类

public class RedisLockUtil {
    private static final Long RELEASE_SUCCESS = 1L;
    private static final String PREFIX = "API_LOCK_";
    /**
     * 释放分布式锁
     *
     * @param jedis
     * @param lockKey
     * @param valve
     * @return boolean
     * @author ll
     * @date 2023/02/09 14:31
     */
    public static boolean unLock(Jedis jedis, String lockKey, String valve) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(PREFIX + lockKey), Collections.singletonList(PREFIX + valve));
        if (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }
    /**
     * 加分布式锁
     *
     * @param jedis
     * @param lockKey
     * @param valve
     * @param timeout
     * @return boolean
     * @author ll
     * @date 2023/02/09 14:31
     */
    public static boolean lock(Jedis jedis, String lockKey, String valve, int timeout) {
        String script = "if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then" +
                " redis.call('expire',KEYS[1],ARGV[2]) return 1 else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(PREFIX + lockKey), Lists.newArrayList(PREFIX + valve, String.valueOf(timeout)));
        //判断是否成功
        if (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }
}

加锁示例(jedis+lua)

@Slf4j
@Component
public class InterfaceEventListener {
    @Resource
    private JedisUtil jedisUtil;
    @Value("${jedis.lock.cycle-number}")
    private int cycleNumber;
    @Value("${jedis.lock.expire-time}")
    private int expireTime;
    @Value("${jedis.lock.sleep-time}")
    private int sleepTime;
    @Value("${spring.redis.database}")
    private int database;
    public void onApplicationEvent(InterfaceEvent event) {
        Jedis jedis = jedisUtil.getJedis();
        jedis.select(database);
        boolean unLock = false;
        boolean lock;
        int currentNumber = 0;
        try {
            do {
                lock = RedisLockUtil.lock(jedis, "lockKey", "valve", expireTime);
                if (lock) {
                    try {
                       //todo 加锁的代码
                    } catch (Exception e) {
                        log.error(e.getMessage());
                        e.printStackTrace();
                    } finally {
                        unLock = RedisLockUtil.unLock(jedis, detectCode, detectCode);
                    }
                }
                currentNumber++;
                Thread.sleep(sleepTime);
            }
            while (!unLock && currentNumber < cycleNumber);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        } finally {
            jedisUtil.close(jedis);
        }
    }
}

以上就是Redis Lua同步锁实现源码解析的详细内容,更多关于Redis Lua同步锁的资料请关注脚本之家其它相关文章!

相关文章

  • 关于redis可视化工具读取数据乱码问题

    关于redis可视化工具读取数据乱码问题

    大家来聊一聊在日常操作redis时用的是什么工具,redis提供的一些命令你都了解了吗,今天通过本文给大家介绍redis可视化工具读取数据乱码问题,感兴趣的朋友跟随小编一起看看吧
    2021-07-07
  • Redis报错:Could not create server TCP listening socket 127.0.0.1:6379: bind:解决方法

    Redis报错:Could not create server TCP 

    这篇文章主要介绍了Redis报错:Could not create server TCP listening socket 127.0.0.1:6379: bind:解决方法,是安装与启动Redis过程中比较常见的问题,需要的朋友可以参考下
    2023-06-06
  • redis列表类型_动力节点Java学院整理

    redis列表类型_动力节点Java学院整理

    这篇文章主要为大家详细介绍了redis列表类型的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • 详解Redis用链表实现消息队列

    详解Redis用链表实现消息队列

    Redis有两种方式实现消息队列,一种是用Redis自带的链表数据结构,另一种是用Redis发布/订阅模式实现,这篇文章先介绍链表实现消息队列,有需要的朋友们可以参考借鉴。
    2016-09-09
  • 了解redis中RDB结构_动力节点Java学院整理

    了解redis中RDB结构_动力节点Java学院整理

    这篇文章主要为大家详细介绍了redis中RDB结构,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • 一文带你了解Redis的三种集群模式

    一文带你了解Redis的三种集群模式

    Redis 的常用的集群方式主要有以下三种,分别是主从复制模式、哨兵模式、Redis-Cluster集群模式,那么下面我们就分别了解一下这三种集群模式的优点与缺点
    2023-06-06
  • 一文搞懂Redis中String数据类型

    一文搞懂Redis中String数据类型

    string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。今天通过本文给大家介绍下Redis中String数据类型,感兴趣的朋友一起看看吧
    2022-04-04
  • Redis cluster集群的介绍

    Redis cluster集群的介绍

    今天小编就为大家分享一篇关于Redis cluster集群的介绍,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • Redis中的慢日志

    Redis中的慢日志

    这篇文章主要介绍了Redis中的慢日志,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • 手把手教你用Redis 实现点赞功能并且与数据库同步

    手把手教你用Redis 实现点赞功能并且与数据库同步

    本文主要介绍了Redis 实现点赞功能并且与数据库同步,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05

最新评论