当前位置: 首页 > news >正文

Redis如何实现分布式锁

目录

获取锁:

释放锁:

Lua脚本:

Redisson


分布式锁是,满足分布式系统或集群模式下多进程可见并且互斥的锁,因为我们熟知的java中的锁只是在单体架构下单个jvm中才会生效,如果部署了多个jvm则会导致新的并发问题。

对于分布式锁我们要确保的五个基本特征:多进程可见性、互斥性、高可用、高性能和安全性

分布式锁的实现常见的有三种:Mysql、Redis和Zookeeper

 这里说一下redis实现分布式锁的操作

获取锁:

互斥:确保只有一个线程获取到锁

非阻塞式:尝试一次,成功返回true,失败返回false

释放锁:

代码层面实现一下:

获取锁,键设置成业务名字(这里拼接了两个字符串),值的话设置成线程id,并设置超时时间

释放锁:

直接删除即可

   这种情况还是会出现一些问题

在极端情况下,如果线程1获取到锁,但是线程1发生了阻塞,阻塞期间锁超时释放,然后此时线程2获取到锁,线程1又醒了之后将线程2获取的锁释放了,这时候线程3又进来了,又会出现线程问题

结局思路就是,在释放锁的时候将储存的线程id取出来(上锁的时候值已经存为线程id),判断是否为当前线程,如果不是就不能释放,只有是当前线程自己的锁才能释放id。

但是这种情况又会在分布式和集群下出现问题,因为线程id是在jvm中维护的一个递增数,解决办法是生产一个uuid拼接线程号表示线程标识,后续判断使用这个新的唯一标识。 

当然,到这里还没完

如果当线程1判断锁是否为自己之后,在准备释放锁的过程中线程阻塞,然后锁超时释放,这时候别的线程2来获得到锁,线程1阻塞结束,就还是会把线程2的锁释放掉,这里就需要确保一下操作的原子性,

Lua脚本:

这里Redid的事务只能确保原子性,无法保证事务的一致性,这里通过lua脚本实现

lua脚本教程地址可参考:Lua 教程 | 菜鸟教程

脚本执行redsi命令可以通过如下命令来实现

redis.call('set','name','jack') 等价于redis中的set name call

Redis调用lua脚本如下

    脚本也可以通过参数传递,如下:

通过lua脚本实现如下功能

lua脚本如下:

再Java中可以通过redisTemplate调用lua脚本,通过execute方法

使用时可以新建一个lua脚本文件,将脚本写入,然后通过DefaultRedisScript的setLocation方法设置脚本位置

然后通过redisTemplate调用execute执行脚本,将脚本和参数传入,这就实现了判断+释放锁代码的原子性,将多行代码变成了一行

当然给予setnx的分布式锁还是存在下面问题:

  1. 不可重入:同一个无法多次获得同一把锁
  2. 不可重试:获取锁只尝试一次就返回,没有重试机制
  3. 超时释放:超时释放虽然可以避免死锁,但是如果业务时间耗时较长,也会导致锁释放,存在安全隐患
  4. 主从一致性:如果redis提供了主从集群,主从同步存在延迟,当主宕机时,如果从同步主中的锁数据回出现问题

为了解决这些问题,redisson提供的这些服务,点击下方跳转redisson笔记

Redisson

Redisson实现分布式锁(看门狗机制)-CSDN博客

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Kali Linux 2024.3 发布,包含新黑客工具
  • 挑战力扣高难度算法、数据库题
  • 基于Arduino Uno开发板实现PWM呼吸灯的设计方案
  • C语言-结构体-详解
  • 【数据结构与算法 | 灵神题单 | 自顶向下DFS篇】力扣1022,623
  • windows11+ubuntu20.04.6双系统安装
  • 数据结构-2.顺序表
  • Delta Function的简单介绍
  • 关于less的基本使用
  • Java设计模式—面向对象设计原则(一) ----->开闭原则OCP(完整详解,附有代码+案例)
  • re题(27)BUUFCTF-[MRCTF2020]Transform
  • C++速通LeetCode简单第18题-杨辉三角(全网唯一递归法)
  • 如何快速解决程序中的BUG
  • 商淘云九周年 分账系统助力企业合规发展
  • 深度学习数据集交通类常见图像分类、目标检测、分割图像数据集(深度学习数据集 - 交通类解决方案)
  • 【JavaScript】通过闭包创建具有私有属性的实例对象
  • Angular数据绑定机制
  • CAP理论的例子讲解
  • FineReport中如何实现自动滚屏效果
  • java8 Stream Pipelines 浅析
  • java8-模拟hadoop
  • JavaScript 基本功--面试宝典
  • Joomla 2.x, 3.x useful code cheatsheet
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • SOFAMosn配置模型
  • Vue 2.3、2.4 知识点小结
  • vue-cli在webpack的配置文件探究
  • XML已死 ?
  • 初识 beanstalkd
  • 仿天猫超市收藏抛物线动画工具库
  • 构建工具 - 收藏集 - 掘金
  • 机器学习中为什么要做归一化normalization
  • 前端_面试
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 入手阿里云新服务器的部署NODE
  • 微信小程序--------语音识别(前端自己也能玩)
  • 微信支付JSAPI,实测!终极方案
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 掌握面试——弹出框的实现(一道题中包含布局/js设计模式)
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 如何正确理解,内页权重高于首页?
  • ​低代码平台的核心价值与优势
  • ​如何防止网络攻击?
  • #Datawhale AI夏令营第4期#AIGC方向 文生图 Task2
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (2)从源码角度聊聊Jetpack Navigator的工作流程
  • (k8s)Kubernetes 从0到1容器编排之旅
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (附源码)c#+winform实现远程开机(广域网可用)
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (接上一篇)前端弄一个变量实现点击次数在前端页面实时更新
  • (三) diretfbrc详解
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424