【Redis】Redis实现分布式锁

【Redis】Redis常见面试题(1)

在这里插入图片描述

文章目录

  • 【Redis】Redis常见面试题(1)
    • 1. 为什么要用分布式锁
    • 2. Redis如何实现分布式锁
    • 3. Redis接受多个请求模拟演示
    • 4. 使用Redis实现分布式锁会存在什么问题
      • 4.1 一个锁被长时间占用
      • 4.2 锁误删

【Redis】Redis常见面试题(1)

1. 为什么要用分布式锁

之前学到的锁,在分布式,微服务是不适用的,因为之前的锁针对的是本地线程,而分布式是跨机器的

而Redis作为一个独立的三方系统,其天生的优势就是可以作为一个分布式系统来使用,因此使用Redis实现的锁都是分布式锁!

在这里插入图片描述

2. Redis如何实现分布式锁

Redis实现分布式锁可以通过setnx(set if not exists)命令实现,当我们使用setnx创建键值成功则表明加锁成功,否则即加锁失败(需要等待锁释放,自旋/挂起等等…);del删除键值,表示锁释放

  • 也就是说,Redis实现锁机制没有那么的高深莫测和复杂,而是一个逻辑概念:
    • 一个锁🔐就是一个键值,争夺锁就是争夺对这个键值的设置权
    • 如果键值被设置了,则说明锁被占用
    • 如果键值不存在,则说明锁没被占用
  • 值是什么具体而论,对于争夺锁的机制而已,是存不存在比较重要
  • 而这个键值对也可以被看成普通的键值对,setnx和del不止用在分布式锁的实现,它们只是具有特殊含义的命令罢了
    • 又由于Redis天生支持分布式系统,所以这个键值可以被所有机器看到(满足了一个前提,所有机器可以setnx 和 del同一个键值),也就是这个锁🔐就是分布式锁

获得锁🔐:

127.0.0.1:6379> setnx lock1 true

在这里插入图片描述

再次获得这把锁:

在这里插入图片描述

在这里插入图片描述

就是个普通键值对~

释放锁🔐

127.0.0.1:6379> del lock1

在这里插入图片描述

再次释放锁:

在这里插入图片描述

那么我们用两个命令行操作redis,模拟两个线程,讲解Redis分布式锁的一些相关问题

在这里插入图片描述

在这里插入图片描述

3. Redis接受多个请求模拟演示

两个命令行“同时”尝试获取锁,总有一个会获取到锁

在这里插入图片描述

黑色命令行选择自旋等待锁:

在这里插入图片描述

直到白色命令行释放锁:

在这里插入图片描述

黑色命令行才获取到锁:

在这里插入图片描述

4. 使用Redis实现分布式锁会存在什么问题

4.1 一个锁被长时间占用

  1. 当一个应用突然奔溃、掉电、莫名其妙下线了,没来得及释放锁
  2. 可能会出现死锁,暂时不考虑可不可以重入锁的问题,N个线程M把锁的问题,也会导致死锁
    • 死锁参考此文章的死锁讲解:【JavaEE】多线程进阶问题-锁策略and死锁,CAS操作,Synchronized原理_s:103的博客-CSDN博客

怎么处理:

  • 设置超时时间
  1. setnx 和 expire搭配使用,不太好,因为这样这条语句就是非原子性的,如果超时时间设置上之前奔溃了,依旧解决不了问题

  2. Redis 2.6.12 版本之后,提供了一个强大的功能,可以让这个操作是原子操作:

    • 在这里插入图片描述

    • 127.0.0.1:6379> set lock true ex 30 nx
      
      • 可以参考后面的题词
      • ex time,单位为秒
      • px time,单位为毫秒
      • 不设置默认永不过期,但是不过期不代表不会被删除掉,这跟数据淘汰机制有关

在这里插入图片描述

4.2 锁误删

由于这个键值对是公共可见的,所以一个线程是可以释放别的线程的锁的!从代码上我们不会出现刻意的删除别的线程的锁的恶劣行为,但是会有一些不可避免的偶然事件场景下,会出现这个问题:

  1. 白色线程抢到了锁🔒,黑色线程自旋

在这里插入图片描述

  1. 但是白色线程执行花了35秒,锁已经自动释放了

在这里插入图片描述

  1. 黑色线程抢到了锁,要执行10秒

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

  1. 白色线程不知道锁被释放并且被抢走了,在第35秒的时候,严谨规范地释放了锁!
    • 即使锁过期了,这也只是Redis的机制,原应用的业务依旧继续执行,(不要误解为应用在Redis中执行!多个应用只是利用的Redis的分布式锁的机制!这里的黑色线程和白色线程只不过是区分两个线程的redis操作)
    • 黑线程不知道自己的锁被释放了,并且锁可能也被其他更多线程获取了,黑线程也可能会误删别人的锁,混乱起来了,线程安全问题大大暴露!

在这里插入图片描述

这有点像,ABA的问题,参考此文章的aba模块:【JavaEE】多线程进阶问题-锁策略and死锁,CAS操作,Synchronized原理_s:103的博客-CSDN博客

解决方法与之类似,(添加一个属性:一个标识或者版本号),保证释放锁是自己刚才抢到的锁!

  • 例如设置不一样的value

白色线程设置white,黑色线程设置black

也就是刚才的第四步,白色线程在释放锁之前,进行判断锁的归属:

在这里插入图片描述

ok,白色线程知道了,不能释放

但是并不是完全没有问题,这个操作是两步的,非原子性操作!

解决方案:

  1. 使用lua脚本,Redis可以识别的可保证原子性的脚本,写多长都是原子性的
  2. 项目使用Redisson框架,有支持原子性的分布式锁 -> 底层还是lua脚本,只不过你不用写,框架帮你写了
    • 一个复杂且好用的东西,总会有框架来方便使用😄

感兴趣的同学可以自行学习:

Redisson · GitHub


文章到此结束!谢谢观看
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭🦆


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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记录vite下使用require报错和解决办法

前情提要 我们现在项目用的是vite4react18开发的项目、但是最近公司有个睿智的人让我把webpack中的bpmn组件迁移过来、结果就出现问题啦:因为webpack是commonjs规范、但是vite不是、好像是es吧、可想而知各种报错 废话不多说啦 直接上代码: 注释是之前c…

CopyOnWriteArrayList源码分析

其中唯一的线程安全 List 实现就是 CopyOnWriteArrayList。 特点 由于读取操作不会对原有数据进行修改,因此,对于每次读取都进行加锁其实是一种资源浪费。相比之下,我们应该允许多个线程同时访问 List 的内部数据,毕竟对于读取操…

(二十八)大数据实战——Flume数据采集之kafka数据生产与消费集成案例

前言 本节内容我们主要介绍一下flume数据采集和kafka消息中间键的整合。通过flume监听nc端口的数据,将数据发送到kafka消息的first主题中,然后在通过flume消费kafka中的主题消息,将消费到的消息打印到控制台上。集成使用flume作为kafka的生产…

JAVA设计模式8:装饰模式,动态地将责任附加到对象上,扩展对象的功能

作者主页:Designer 小郑 作者简介:3年JAVA全栈开发经验,专注JAVA技术、系统定制、远程指导,致力于企业数字化转型,CSDN博客专家,阿里云社区专家博主,蓝桥云课讲师。 目录 一、什么是装饰模式二、…

春秋云镜 CVE-2015-1427

春秋云镜 CVE-2015-1427 ElasticSearch RCE 靶标介绍 ElasticSearch RCE 启动场景 漏洞利用 因查询时至少要求es中有一条数据,所以发送如下数据包,增加一个数据: POST /website/blog/ HTTP/1.1 Host: eci-2zedttamjkr80i9iubel.cloudeci…

VMware ubuntu空间越用越大

前言 用Ubuntu 1604编译了RK3399的SDK,之后删了一些多余的文件,df - h 已用21G,但window硬盘上还总用了185GB,采用了碎片整理,压缩无法解决 1 启动Ubuntu后, 安装 VMware Tools(T) 、 2 打开ubuntu终端,压…

Revit SDK 介绍:Ribbon 界面

前言 Revit 通过 API 将完整的 Ribbon 做了保留,同时这些菜单按钮也可以和相应的命令绑定。 内容 运行效果如下所示: 菜单特写: Ribbon Sample 整体是 API 暴露出来的一个 RibbonPanel,对应的接口: namespace Au…

FPGA GTH aurora 8b/10b编解码 PCIE 视频传输,提供2套工程源码加QT上位机源码和技术支持

目录 1、前言免责声明 2、我这里已有的 GT 高速接口解决方案3、GTH 全网最细解读GTH 基本结构GTH 发送和接收处理流程GTH 的参考时钟GTH 发送接口GTH 接收接口GTH IP核调用和使用 4、设计思路框架视频源选择silicon9011解码芯片配置及采集动态彩条视频数据组包GTH aurora 8b/10…

Java native 关键字

如你在看 JDK 的源代码的时候,大概率会看到很多方法使用了 native 关键字。 下面是 String 对象 JDK 中的源代码,就带有了一个 native 关键字。 native 是干什么用的 简单来说就是 Java 的 native 方法的实现不是用 Java 实现的,可能在其他…

Flutter 中的单元测试:从工作流基础到复杂场景

对 Flutter 的兴趣空前高涨——而且早就应该出现了。 Google 的开源 SDK 与 Android、iOS、macOS、Web、Windows 和 Linux 兼容。单个 Flutter 代码库支持所有这些。单元测试有助于交付一致且可靠的 Flutter 应用程序,通过在组装之前先发制人地提高代码质量来确保不…

数据结构与算法(二)——前缀、中缀、后缀表达式

一、前缀表达式(波兰表达式) 1.1、计算机求值 从右至左扫描表达式,遇到数字时,将数字压入堆栈。遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 和 次顶元素&#xff09…

Navicat导入Excel数据顺序变了

项目场景: Navicat导入Excel数据 问题描述 从Excel表格中导入数据到数据库中。但是,在导入的过程中,我们常会发现数据顺序出现了问题,导致数据错位,给数据的处理带来了极大的麻烦。 原因分析: 这个问题的…

mybatisplus配置拦截器实现保存加密,输出解密,模糊查询

前言:因公司需求需要把某些实体类的某些字段值进行加密保存,在查询时解密明文输出。现记录两种方式。 一、第一种方式: (1)使用TableField(typeHandler TypeHandler.class)注解自带的字段类型处理器,写一…

电脑死机的时候,CPU到底在做什么?

电脑死机,应该每个接触计算机的小伙伴都经历过吧。 尤其是早些年,电脑配置还没现在这么高的时候,多开几个重量级应用程序,死机就能如约而至,就算你把键盘上的CTRLALTDELETE按烂了,任务管理器也出不来&…

Mybatis-Genertor逆向工程

1、导入mybaties插件 <build><plugins><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.4.2</version><dependencies><dependency>…

Error: svn: E155004: Run ‘svn cleanup‘ to remove locks

解决办法如下&#xff1a;点击settings 点击清除缓存按钮&#xff0c;然后再使用svn进行提交更新操作&#xff0c;但是可能还会有其它的错误&#xff0c;比如svn: E230001: Server SSL certificate verification failed&#xff0c;解决这个错误请参考我另一篇文章&#xff1a;…

博客系统(升级(Spring))(一)创建数据库,创建实例化对象,统一数据格式,统一报错信息

博客系统&#xff08;一&#xff09; 博客系统一、创建项目二、建立数据库结构链接服务器和数据库和Redis 三、创建实例化对象四、统一数据结构结构 五、统一报错信息 博客系统 博客系统是干什么的&#xff1f; CSDN就是一个典型的博客系统。而我在这里就是通过模拟实现一个博…

Python+Requests+Excel接口测试实战

1、EXCEL文件接口保存方式&#xff0c;如图。 2、然后就是读取EXCEL文件中的数据方法&#xff0c;如下&#xff1a; 1 import xlrd2 3 4 class readExcel(object):5 def __init__(self, path):6 self.path path7 8 property9 def getSheet(self): 10 …

莫比乌斯召回系统介绍

当前召回系统只能召回相关性高的广告&#xff0c;但不能保证该广告变现能力强。莫比乌斯做了如下两点创新&#xff1a; 在召回阶段&#xff0c;引入CPM等业务指标作为召回依据在召回阶段&#xff0c;引入CTR模型&#xff0c;从而召回更多相关性高且变现能力强的广告 参考 百度…

基于Protege的知识建模实战

一.Protege简介、用途和特点 1.Protege简介 Protege是斯坦福大学医学院生物信息研究中心基于Java开发的本体编辑和本体开发工具&#xff0c;也是基于知识的编辑器&#xff0c;属于开放源代码软件。这个软件主要用于语义网中本体的构建&#xff0c;是语义网中本体构建的核心开发…