Redis进阶:分布式锁问题

news2024/11/25 2:50:34

分布式锁问题

  • 1. 分布式锁问题
    • 1.1 问题介绍
    • 1.2 解决方案
      • 1.2.1 分布式锁主流的实现方案
      • 1.2.2 使用Redis实现分布式锁
      • 1.2.3 分布式锁需要满足的四个条件
    • 1.3 实现分布式锁

1. 分布式锁问题

1.1 问题介绍

  • 单机单体中的锁机制在分布式集群系统中失效;
  • 单纯的Java API并不能提供分布式锁的能力,为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问;

1.2 解决方案

1.2.1 分布式锁主流的实现方案

  • 基于数据库实现分布式锁;
  • 基于缓存(Redis等),性能最高
  • 基于Zookeeper,可靠性最高;

1.2.2 使用Redis实现分布式锁

在这里插入图片描述

  • 使用set命令添加一个mutex key,同时为该key设置过时时间,并要求该key存在时无法更新数据
  • 通过set命令设置的mutex key即为分布式锁,在该key过时或被删除以前,此key无法被其他请求获取到;
  • 具体可通过set mutex_key uuid nx ex 过期时间进行加锁,其中mutex_key为锁名,value为一唯一值,过期时间以秒为单位;
  • 可通过del mutex_key 手动释放锁,但缺乏原子性,可通过lua脚本进行删除保证操作原子性
    在这里插入图片描述
  • set命令中使用UUID做value是为了解决该问题:当前服务器可能释放其他服务器的锁,而自身的锁也可能被其他服务器释放
  • UUID是一个唯一值,用于标识不同的服务器;

在这里插入图片描述
在这里插入图片描述

1.2.3 分布式锁需要满足的四个条件

  • 互斥性:在任意时刻,只有一个客户端能持有锁;
  • 不会发生死锁:即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁;
  • 解铃还须系铃人:加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了;
  • 加锁和解锁必须具有原子性

1.3 实现分布式锁

  • 基于SpringBoot框架,常用配置参考https://springdoc.cn/spring-boot/application-properties.html#application-properties.data.spring.data.redis.cluster.nodes;
  • 代码:
    // 分布式锁测试
    @RequestMapping("/lockTest")
    public void lockTest(){
        String uuid= UUID.randomUUID().toString();
        // 获取锁
        Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 10, TimeUnit.SECONDS);
        // 成功获取锁
        if (lock){
            // 逻辑业务
            Object value = redisTemplate.opsForValue().get("num");
            if(StringUtils.isEmpty(value)){
                return;
            }
            Long num = Long.parseLong(value+"");
            redisTemplate.opsForValue().set("num",num+1);
            // 手动释放锁
            String lockVal = (String) redisTemplate.opsForValue().get("lock");
            if (lockVal.equals(uuid)) {
                redisTemplate.delete("lock");
            }
            // 定义lua脚本
            String luaScript="if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1])" +
                    "else return 0 end";
            DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
            redisScript.setScriptText(luaScript);
            redisScript.setResultType(Long.class);
            // 第一个要是script 脚本 ,第二个需要判断的key,第三个就是key所对应的值
            redisTemplate.execute(redisScript, Arrays.asList("lock"),uuid);
        }else{
            // 等待一会再重新尝试获取锁
            try {
                Thread.sleep(100);
                lockTest();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/616637.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux快速安装MySQL

文章目录 Linux上安装MySQL1. 安装MySQL1&#xff09;上传MySQL安装包以及MySQL驱动jar包2&#xff09;解压MySQL安装包3&#xff09;卸载系统自带的mariadb4&#xff09;安装MySQL依赖5&#xff09;安装mysql-client6&#xff09;安装mysql-server7&#xff09;启动MySQL8&…

案例27:基于Java宠物领养系统开题报告设计

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

性能测试之Docker监控

相信很多程序员在进行性能测试时常常会遇到一些问题&#xff0c;比如如何监控Docker容器的运行状态。这时候&#xff0c;Docker监控工具就派上了用场。 我曾经也遇到过这样的问题&#xff0c;不知道如何获取Docker容器的性能数据&#xff0c;直到我发现了Docker监控工具。使用…

干货分享 | TSMaster小功能之实时注释在图形中的使用技巧

今天给大家介绍TSMaster功能之实时注释在图形中的使用技巧&#xff0c;主要通过手动注释、自动化注释、实时注释在记录与回放中的运用等三方面来进行介绍。 一、实时注释的作用 在了解实时注释的使用技巧之前&#xff0c;我们先了解一下实时注释是什么以及它的作用。 实时注释…

算法修炼之筑基篇——筑基二层初期(解决最长回文子串问题,马拉车(manacher)算法模板)

✨博主&#xff1a;命运之光 &#x1f984;专栏&#xff1a;算法修炼之练气篇 &#x1f353;专栏&#xff1a;算法修炼之筑基篇 ✨博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;学习了算法修炼之练气篇想必各位蒟蒻们的基础已经非常的扎实了&#xff0c;下来…

SpringCloud服务注册中心

SpringCloud 服务注册中心 1.Eureka基础知识 什么是服务治理? Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务治理 在传统的rpc远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务与服务之间的依赖关系,…

数据库的增删改查(三)

1、查询 1.1、聚合查询 1.1.1、聚合函数 数据库提供了很多函数&#xff0c;其中就包括聚合函数&#xff0c;常见的聚合函数如下表 函数说明COUNT([IDDINCT] expr)返回查询到的数据的数量SUM([DISTINCT] expr)返回查询到的数据的总和&#xff0c;不是数字没有意义AVG([IDSTI…

一篇长文教你进行全方位的使用appium

随着移动应用的日益普及&#xff0c;移动应用的测试成为了软件开发的重要组成部分。Python&#xff0c;作为一种易于学习&#xff0c;功能强大的编程语言&#xff0c;特别适合进行这种测试。本文将详细介绍如何使用Python进行APP测试&#xff0c;并附带一个实例。 Python 和 Ap…

CVE漏洞复现-CVE-2021-2109 Weblogic Server远程代码执行

CVE-2021-2109 Weblogic Server远程代码执行 漏洞背景 2021年1月20日&#xff0c;Oracle官方发布了漏洞补丁&#xff0c;修了包括 CVE-2021-2109 Weblogic Server远程代码执行漏洞在内的多个高危严重漏洞。CVE-2021-2109 中&#xff0c;攻击者可构造恶意请求&#xff0c;造成J…

多媒体库SDL以及实时音视频库WebRTC中的多线程问题实战详解

目录 1、概述 2、开源跨平台多媒体库SDL介绍 3、开源音视频实时通信库WebRTC介绍 4、在国产化Linux桌面系统中遇到的SDL多线程问题 5、在给WebRTC新增外部音频插件库时遇到的多线程问题 6、最后 VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xf…

【云原生】创建容器的方法

1&#xff09;基于现有镜像的创建 先使用现有镜像创建容器 docker run 再进入容器进行内容更新 docker exec 最后提交成新的镜像 docker commit 2&#xff09;基于模板创建 可以从本地容器导出模板文件 docker export 或者从网上下载现成的模板文件 http://openvz…

C++继承相关内容(二)

目录 一.拷贝构造函数 第一种情况&#xff1a;基类没有拷贝构造函数&#xff0c;派生类也没有拷贝构造函数 结果&#xff1a; 原因&#xff1a; 第二种情况&#xff1a;基类没有拷贝构造函数&#xff0c;派生类有拷贝构造函数 结果&#xff1a; 原因&#xff1a; 第三种情况…

【文生图系列】 Stable Diffusion v2复现教程

文章目录 xformersbug 记录 txt2imgdiffusers参考 基础环境承接Stable Diffusion v1, 详情请见我的博文【文生图系列】 Stable Diffusion v1复现教程。然后更新pytorch和torchvision的版本&#xff0c;因为要使用GPU和xformers&#xff0c;需要下载gpu版本的pytorch。再下载ope…

学习笔记之微服务(一)

一、了解微服务 1、服务架构演变 **单体架构&#xff1a;**所有业务功能都集中在一个项目中开发&#xff0c;打成一个包部署。 优点&#xff1a;架构简单、部署成本低 缺点&#xff1a;耦合度高 分布式架构&#xff1a;根据业务拆分系统功能&#xff0c;每个业务模块独立项…

微信小程序map 之个性化地图(日出日落主题)

微信小程序map 之个性化地图&#xff08;日出日落主题&#xff09; 个性化地图之根据日出日落时间动态变换地图主题个性化前的准备进入腾讯地址服务官网小程序开发html 代码. layer-style 编号为样式名称js代码. 注意的是&#xff0c;layer-style只能定义一次&#xff0c;所以值…

Yarn【常用命令】

1、yarn application 查看Application运行情况 1.1、列出所有Application yarn application -list 可以通过Web UI端来查看&#xff1a; 1.2、根据Application状态过滤&#xff1a; yarn application -list -appStates &#xff08;所有状态&#xff1a; ALL 、 NEW 、 NEW…

Spring Cloud Alibaba 同时兼容dubbo与openfeign

一、前言 dubbo与springcloud都可以单独作为微服务治理框架在生产中进行使用&#xff0c;但使用过springcloud的同学大概了解到&#xff0c;springcloud生态的相关组件这些年已经逐步停更&#xff0c;这就导致在服务架构演进过程中的迭代断层&#xff0c;以至于一些新的技术组…

聚合/组合

谨慎使用继承的方式来进行扩展&#xff0c;优先使用聚合/组合的方式来实现。 Father类里有两个方法A和方法B&#xff0c;并且A调用了B。子类Son重写了方法B&#xff0c;这时候如果子类调用继承来的方法A&#xff0c;那么方法A调用的就不再是Father.B()&#xff0c;而是子类中的…

使用kali里的dnschef进行DNS欺骗

1. 前言 DNSChef是针对渗透测试人员和恶意软件分析师的高度可配置的DNS代理。它能够精细配置哪些DNS回复以修改或简单地代理真实响应。为了利用该工具&#xff0c;您必须手动配置DNS服务器以指向DNSChef。 2. 执行参数 选项参数&#xff1a; -h,--help显示帮助信息并退出--f…

C语言:计算 1! + 2! + 3! + ... + n!

题目&#xff1a; 从键盘输入一个值n&#xff0c;计算 1的阶乘 至 n的阶乘 的和&#xff0c; 如&#xff1a;输入10&#xff0c;计算 1的阶乘 至 n的阶乘 的和 --> 计算&#xff1a;1! 2! 3! ... 10! 思路一&#xff1a; 效率比较低&#xff0c;会重复计算之前计算过的…