【Redis 开发】分布式锁中的常见问题和Lua脚本

这篇具有很好参考价值的文章主要介绍了【Redis 开发】分布式锁中的常见问题和Lua脚本。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

分布式锁中的问题

分布式锁中我们设置的过期时间:
如果有一个线程获取锁之后在进行操作时,到达了锁的过期时间,之后就会有别的线程获得锁,如果这时,第一个线程执行完成后释放锁,就会将第二个锁的线程删除

针对这个情况如何改进:

  1. 在获取锁时存入线程标示(可以用UUID)
  2. 在释放锁时先获取锁中的线程标示,判断是否与当前线程标识一致
  3. 如果一致则释放锁
  4. 如果不一致则不释放锁

改进分布式锁添加释放锁的判断

public class SimpleRedisLock implements ILock{

    private String name;
    private StringRedisTemplate stringRedisTemplate;

    public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {
        this.name = name;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    private static final String key_prefix="lock:";
    private static final String id_prefix= UUID.randomUUID().toString()+"-";
    @Override
    public boolean tryLock(long timeoutSec) {
        //获取线程的标识
        String threadId= id_prefix+Thread.currentThread().getId();
        Boolean aBoolean = stringRedisTemplate.opsForValue().setIfAbsent(key_prefix + name, threadId, timeoutSec, TimeUnit.SECONDS);
        //自动拆箱的返回
        return Boolean.TRUE.equals(aBoolean);
    }

    @Override
    public void unlock() {
        //获取线程标识
        String threadid = id_prefix + Thread.currentThread().getId();
        //获取锁中的标识
        String s = stringRedisTemplate.opsForValue().get(key_prefix + name);
        //判断标识是否一致
        if(threadid.equals(s)) {
            //释放锁
            stringRedisTemplate.delete(key_prefix+name);
        }
        
    }
}

上述我们做了修改进行判断,但是还存在一种极端情况,当线程操作完毕需要释放锁的时候,这个时候已经判断完毕,但是由于比如说垃圾回收等问题对线程的释放操作进行阻塞,这个时候如果超过等待时间,这是还是会出现上述问题,在阻塞结束之后,会删除其他线程的锁

要彻底避免这种情况的发生,需要将判断锁标识的动作与释放锁标识的动作进行原子性操作,此时就会用到Lua脚本

Lua脚本

Redis提供了Lua脚本功能,在一个脚本中编写多条Redis命令,确保多条命令执行时的原子性,Lua脚本时一种编程语言
地址:https://www.runoob.com/lua/lua-tutorial.html

编写Lua脚本

---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by LENOVO.
--- DateTime: 2024/4/26 19:01
---比较线程标识与锁中的标识是否一致
if(redis.call('get',KEY[1]) == ARGV[1]) then
    --- 释放锁资源
    return redis.call('del',KEY[1])
end
return 0

调用Lua脚本:

    @Override
    public void unlock() {
        //调用lua脚本
        stringRedisTemplate.execute(
                UNLOCK_SCRIPT,
                Collections.singletonList(key_prefix+name),
                id_prefix+Thread.currentThread().getId());
    }

其中的UNLOCK_SCRIPT是脚本对象,需要提前进行定义文章来源地址https://www.toymoban.com/news/detail-861130.html

    //设置脚本对象
    private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;

    static{
        UNLOCK_SCRIPT =new DefaultRedisScript<>();
        UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
        UNLOCK_SCRIPT.setResultType(Long.class);
    }

到了这里,关于【Redis 开发】分布式锁中的常见问题和Lua脚本的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • redis集群和分片-Redis Cluster:分布式环境中的数据分片、主从复制和 Sentinel 哨兵

    当涉及到 Redis 中的集群、分片、主从复制和 Sentinel 哨兵时,这些是构建分布式 Redis 环境中非常重要的概念和组件。下面详细介绍这些概念以及它们在分布式环境中的作用。 Redis Cluster 是 Redis 官方提供的分布式解决方案,用于管理和维护多个 Redis 节点的分布式数据存储。R

    2024年02月13日
    浏览(61)
  • 【技术驿站】分布式基础与常见面试问题

    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老 导航 檀越剑指大厂系列:全面总

    2024年02月04日
    浏览(47)
  • Jmeter分布式测试的注意事项和常见问题

    Jmeter是一款开源的性能测试工具,使用Jmeter进行分布式测试时,也需要注意一些细节和问题,否则可能会影响测试结果的准确性和可靠性。 如果使用csv文件进行参数化,即通过读取csv文件中的数据来为测试脚本提供不同的输入值,那么需要注意以下两点: 需要把参数文件在

    2024年02月06日
    浏览(46)
  • 性能测试 —— Jmeter分布式测试的注意事项和常见问题

    Jmeter是一款开源的性能测试工具,使用Jmeter进行分布式测试时,也需要注意一些细节和问题,否则可能会影响测试结果的准确性和可靠性。 Jmeter分布式测试时需要特别注意的几个方面 1. 参数化文件的位置和内容 如果使用csv文件进行参数化,即通过读取csv文件中的数据来为测

    2024年02月05日
    浏览(43)
  • Redis与分布式-分布式锁

    接上文 Redis与分布式-集群搭建 为了解决上述问题,可以利用分布式锁来实现。 重新复制一份redis,配置文件都是刚下载时候的不用更改,然后启动redis服务和redis客户。 redis存在这样的命令:和set命令差不多,但是它有一个机制,当指定的key不存在的时候,才能进行插入,实

    2024年02月07日
    浏览(50)
  • Redis分布式锁和分布式事务

    Redis分布式锁和分布式事务 一、Redis分布式锁 1.1 watch和事务实现分布式锁 原理是通过watch来观察一个变量,一个线程在操作的时候,其他线程会操作失败,相当于乐观锁。 1.2 setnx实现分布式锁 原理是通过setnx设置一个变量,设置成功的线程抢到锁,执行相关的业务,执行完毕

    2024年02月09日
    浏览(45)
  • 【软件开发/设计】分布式架构中的组件(如Kafka、MongoDB和Nginx)如何进行容器化部署

    容器化部署是将应用程序及其依赖打包成一个容器镜像,然后在任何支持容器的环境中运行这个镜像的过程。在分布式架构中,像Nginx、MongoDB、Kafka这样的组件通过容器化可以更易于部署、扩展和管理。以下是这些组件容器化部署的一般步骤和原理: 容器化部署的一般步骤

    2024年02月04日
    浏览(48)
  • 【redis】redis分布式锁

    一、为什么需要分布式锁 1.在java单机服务中,jvm内部有一个全局的锁监视器,只有一个线程能获取到锁,可以实现线程之间的互斥 2.当有多个java服务时,会有多个jvm,也会有多个锁监视器,这样没办法使得多个jvm之间的线程互斥,所以无法使用jvm内部的锁监视器,也就是s

    2023年04月25日
    浏览(45)
  • 分布式锁实现(mysql,以及redis)以及分布式的概念

    我旁边的一位老哥跟我说,你知道分布式是是用来干什么的嘛?一句话给我干懵了,我能隐含知道,大概是用来做分压处理的,并增加系统稳定性的。但是具体如何,我却道不出个1,2,3。现在就将这些做一个详细的总结。至少以后碰到面试官可以说上个123。 那么就正式进入

    2024年01月21日
    浏览(61)
  • 分布式系统面试全集通第一篇(dubbo+redis+zookeeper----分布式+CAP+BASE+分布式事务+分布式锁)

    什么是分布式 一个系统各组件分别部署在不同服务器。彼此通过网络通信和协调的系统。 也可以指多个不同组件分布在网络上互相协作,比如说电商网站 也可以一个组件的多个副本组成集群,互相协作如同一个组件,比如数据存储服务中为了数据不丢失而采取的多个服务备

    2024年04月11日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包