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 Cluster或Codis)中,数据(内存占用)或访问请求(QPS)没有均匀地分布到各个节点上,导致部分节点负载过高,而其他节点相对空闲的现象,文章详细介绍了Redis数据倾斜的概念、原因、诊断方法以及解决方案,感兴趣的朋友一起看看吧
    2026-01-01
  • Redis闪退的三种解决办法(windows版本)

    Redis闪退的三种解决办法(windows版本)

    目前大部分的项目都需要redis缓存,有时候我们会遇见打开redis缓存出现闪退的状况,本文小编给大家介绍了Redis闪退的三种解决办法(windows版本),通过图文介绍的非常详细,需要的朋友可以参考下
    2025-04-04
  • redis和rabbitmq实现延时队列的示例代码

    redis和rabbitmq实现延时队列的示例代码

    在高并发场景下,延迟队列显得尤为重要,本文主要介绍了两种方式,redis和rabbitmq实现延时队列,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • Redis内存碎片处理实例详解

    Redis内存碎片处理实例详解

    内存碎片是redis服务中分配器分配存储对象内存的时产生的,下面这篇文章主要给大家介绍了关于Redis内存碎片处理的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-05-05
  • Redis持久化使用及说明(RDB&AOF)

    Redis持久化使用及说明(RDB&AOF)

    Redis通过RDB(定期快照)和AOF(日志记录)实现持久化,兼顾内存性能与数据安全,RDB文件紧凑,适合冷备;AOF实时性强,但体积较大,两者结合使用(混合持久化)可平衡效率与可靠性,确保数据在异常重启时恢复
    2025-08-08
  • 基于Redis实现附近商铺查询功能

    基于Redis实现附近商铺查询功能

    这篇文章主要介绍了基于Redis实现-附近商铺查询功能,这个功能将使用到Redis中的GEO这种数据结构来实现,需要的朋友可以参考下
    2025-05-05
  • React 组件的常用生命周期函数汇总

    React 组件的常用生命周期函数汇总

    这篇文章主要介绍了React 组件的常用生命周期函数汇总,组件的生命周期有助于理解组件的运行方式、完成更复杂的组件功能、分析组件错误原因等
    2022-08-08
  • 关于Redis中bitmap的原理和使用详解

    关于Redis中bitmap的原理和使用详解

    这篇文章主要介绍了关于Redis中bitmap的原理和使用详解,BitMap即位图,使用每个位表示某种状态,适合处理整型的海量数据,本质上是哈希表的一种应用实现,需要的朋友可以参考下
    2023-05-05
  • redis的scan使用方法及在spring框架使用详解

    redis的scan使用方法及在spring框架使用详解

    Redis的SCAN命令是一种非阻塞的迭代器,用于逐步遍历数据库中的键,特别适合处理大数据库,下面详细介绍其使用方法及在Spring框架中的集成方式,感兴趣的朋友跟随小编一起看看吧
    2025-09-09
  • spring boot整合redis中间件与热部署实现代码

    spring boot整合redis中间件与热部署实现代码

    spring boot整合redis最常用的有三个工具库Jedis,Redisson,Lettuce,本文重点介绍spring boot整合redis中间件与热部署实现,需要的朋友可以参考下
    2023-01-01

最新评论