Redis?Lua同步锁实现源码解析

 更新时间:2023年05月18日 10:43:23   作者:多喝灬丶烫水  
这篇文章主要为大家介绍了Redis?Lua同步锁实现源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

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集群指定主从关系及动态增删节点方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Redis基本数据类型Zset有序集合常用操作

    Redis基本数据类型Zset有序集合常用操作

    这篇文章主要为大家介绍了redis基本数据类型Zset有序集合常用操作,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • 关于redis可视化工具读取数据乱码问题

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

    大家来聊一聊在日常操作redis时用的是什么工具,redis提供的一些命令你都了解了吗,今天通过本文给大家介绍redis可视化工具读取数据乱码问题,感兴趣的朋友跟随小编一起看看吧
    2021-07-07
  • 几分钟教你掌握Redis简单动态字符串SDS

    几分钟教你掌握Redis简单动态字符串SDS

    这篇文章主要为大家介绍了几分钟教你掌握Redis简单动态字符串SDS方法,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Redis设置密码的实现步骤

    Redis设置密码的实现步骤

    本文主要介绍了Redis设置密码的实现步骤,主要包括两种方法:临时密码和持久密码,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • redis中数据类型命令整理

    redis中数据类型命令整理

    在本篇文章里小编给大家整理的是关于redis中5种数据类型基本命令介绍,需要的朋友们可以学习下。
    2020-03-03
  • 利用redis实现聊天记录转存功能的全过程

    利用redis实现聊天记录转存功能的全过程

    社交类软件聊天功能必不可少,聊天记录存储的方式也比较多,比如文本,数据库,云等等,但是最好的选择还是redis进行存储,这篇文章主要给大家介绍了关于如何利用redis实现聊天记录转存功能的相关资料,需要的朋友可以参考下
    2021-08-08
  • redis主从连接不成功错误问题及解决

    redis主从连接不成功错误问题及解决

    这篇文章主要介绍了redis主从连接不成功错误问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教<BR>
    2024-01-01
  • Redis如何优雅的删除特定前缀key

    Redis如何优雅的删除特定前缀key

    这篇文章主要给大家介绍了关于Redis如何优雅的删除特定前缀key的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Redis具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • 利用Supervisor管理Redis进程的方法教程

    利用Supervisor管理Redis进程的方法教程

    Supervisor 是可以在类 UNIX 系统中进行管理和监控各种进程的小型系统。它自带了客户端和服务端工具,下面这篇文章主要给大家介绍了关于利用Supervisor管理Redis进程的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-08-08

最新评论

?


http://www.vxiaotou.com