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

【redis】redis分布式锁

目录

        • 一、为什么需要分布式锁
        • 二、分布式锁的实现方案
        • 三、redis分布式锁
          • 3.1 简单实现
          • 3.2 成熟的实现

一、为什么需要分布式锁

  • 1.在java单机服务中,jvm内部有一个全局的锁监视器,只有一个线程能获取到锁,可以实现线程之间的互斥
  • 2.当有多个java服务时,会有多个jvm,也会有多个锁监视器,这样没办法使得多个jvm之间的线程互斥,所以无法使用jvm内部的锁监视器,也就是synchronized关键字无法用于此场景
  • 3.需要在多个jvm外部加一个锁监视器,这样保证不同的jvm的线程保持互斥
  • 4.满足分布式系统或者集群模式下多个进程都可见并且互斥的锁
  • 5.分布式锁满足的特性:多进程可见、互斥、高可用、高性能、安全
  • 6.分布式锁是否可重入
  • 7.分布式锁是否公平

二、分布式锁的实现方案

  • 1.mysql实现:利用mysql内部的写操作(本身的互斥锁),可以开启一个事务,执行业务,业务执行完之后,提交事务释放锁,当业务出现异常,事务回滚,释放锁。可用性好,性能一般,断开连接也会释放锁,是安全的
  • 2.redis实现:利用setnx的互斥命令,当key存在的时候set值会失败,当key不存在的时候才会set成功,删除key之后,锁便能释放。redis集群,可用性得到保障,高性能。给key加上过期时间,即使服务器宕机,redis重启,key到期失效锁也会自动失效,解决安全性问题。key的过期时间也是有讲究的,如果过短,业务还未处理完便释放了锁,会有问题。如果过长,无效的等待时间会变多。
  • 3.zookeeper实现:利用节点的唯一性和有序性实现互斥。zookeeper可以集群,可用性好,zookeeper是强一致性,性能上比redis差,节点是临时节点,服务器宕机,节点断开连接会自动释放

三、redis分布式锁

3.1 简单实现
  • 1.获取锁:setnx lock thread,lock不存在则设置key,lock存在则设置不了lock
  • 2.释放锁:del key,如果服务宕机,没有del key,会导致key一直存在,造成死锁
  • 3.设置过期时间:expire lock 10,lock在10秒后自动过期
  • 4.若setnx lock thread之后,还没来得及expire lock 10,服务器宕机,仍然会死锁,是用一个set命令保证原子性,即set lock thread ex 10 nx
  • 5.获取锁失败会有两种机制,一是继续等待,等到有线程释放锁为止,阻塞式获取,二是非阻塞是获取,如果获取失败,会尝试再获取一次,如果还是失败则立即结束返回结果。阻塞式实现比较麻烦,对cpu也会产生压力
  • 6.非阻塞式分布式锁实现过程:尝试获取锁,获取锁成功,执行业务,业务如果超时或者宕机则释放锁,业务执行完毕也会释放锁
  • 7.误删锁情况:线程1获取到锁,由于业务处理时间过长,锁超时释放,此时线程2获取到锁,执行业务,业务时间也长,线程1此时业务处理完毕,然后释放了锁,线程3此时拿到锁执行业务,那么此时线程2和线程3的执行业务就是非互斥的,造成并发不安全。
  • 8.对于无删除锁情况,锁的value中应该存一份线程的标识(可以用uuid,若是线程的id,集群情况下会发生线程id重复的情况),实现过程:线程1获取到锁,并存入线程标识,获取锁成功,开始执行业务,若业务超时或服务宕机,自动释放锁,若业务执行完毕且没有超时,判断锁标识是否是线程1的,如果是则释放锁
  • 9.非原子操作情况:线程1获取到锁,然后处理业务,业务处理完毕,准备释放锁,判断锁标识是否是线程1的,判断是的,开始释放锁,此时线程1阻塞(jvm发生FullGC),导致redis锁超时释放,GC完毕,线程2获取到锁,开始执行业务,业务时间较长,线程1阻塞结束,释放掉了锁,线程3获取到锁,执行业务,此时线程2和线程3的业务处理产生并发问题。所以需要线程1判断锁标识的操作和释放锁的操作要保证原子性,需要用lua脚本实现
  • 10.还有其它问题,例如不可重入,同一个线程无法多次获取同一个锁;不可重试,获取锁只尝试一次就返回false,没有重试机制;超时释放,超时释放可以避免死锁,但业务处理时间过长,导致锁超时释放,会存在安全隐患;主从一致性问题,如果redis提供了主从集群,线程1在主机上设置了锁,主从同步存在延迟,当主机宕机时,从机没有同步到主机上的锁数据,线程2读从机时未发现到锁,线程2也能拿到锁,此时从机被推选为主机,并缓存了线程2的锁,此时线程1和线程2在业务处理上存在并发问题
3.2 成熟的实现
  • 1.开源框架redission

相关文章:

【redis】redis分布式锁

目录一、为什么需要分布式锁二、分布式锁的实现方案三、redis分布式锁3.1 简单实现3.2 成熟的实现一、为什么需要分布式锁 1.在java单机服务中,jvm内部有一个全局的锁监视器,只有一个线程能获取到锁,可以实现线程之间的互斥 2.当有多个java服…...

UEditorPlus v3.0.0 接口请求头参数,插入换行优化,若干问题优化

UEditor是由百度开发的所见即所得的开源富文本编辑器,基于MIT开源协议,该富文本编辑器帮助不少网站开发者解决富文本编辑器的难点。 UEditorPlus 是有 ModStart 团队基于 UEditor 二次开发的富文本编辑器,主要做了样式的定制,更符…...

LabVIEW 2015介绍

这里写目录标题LabVIEW 2015安装包LabVIEW 2020安装包Labview2015安装过程1、LabVIEW 2015 的介绍2、LabVIEW 2015 的特点3、LabVIEW 2015 的功能4、LabVIEW 2015 快捷键LabVIEW 2015安装包 链接:https://pan.baidu.com/s/1I1cxtbBkmJbHvDTc5JnOyQ 提取码&#xff1…...

大一被忽悠进了培训班

大家好,我是帅地。 最近我的知识星球开始营业,不少大一大二的小伙伴也是纷纷加入了星球,并且咨询的问题也是五花八门,反正就是,各种迷茫,其中有一个学弟,才大一,就报考培训班&#…...

编写一个存储过程,输入一个日期,判定其距离年底还有多少天

--编写一个存储过程,输入一个日期,判定其距离年底还有多少天 create or replace procedure sp_end(i_date varchar2,o_end out varchar2) is --声明两个变量,v_end存放经过转化的年底日期,v_errm用来存放异常 v_end date; v_errm…...

HTB-Inject

HTB-Inject信息收集开机root信息收集 228080 8080端口如下。 主界面有一个上传图片的功能。 简单测试后发现对上传文件后缀名应该有过滤,只允许jpg后缀名文件上传。将一个内容为”test“的txt文件修改后缀为jpg后上传会出现错误。 验证一下是否存在LFI。 验证一…...

java基础知识——13.类与对象

这篇文章,我们来介绍java中的类与对象 目录 1.面向对象的介绍 2.类的设计与使用 2.1 类和对象 2.1.1 如何定义类 2.2 类的注意事项 3.封装 3.1 private关键字 4.this关键字 5.构造方法 6.标准JavaBean 7.对象内存图 8.成员变量与局部变量 1.面向对象的…...

北邮22信通:(10)第三章 3.2栈的实现

北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 上一篇文章: 北邮22信通:(9)实验1 题目六:模拟内存管理(搬运官方代码)_青…...

Vue3之使用js实现动画

概述 动画的实现其实不仅可以使用CSS的方式实现,而且还可以使用js的方式实现,二者有啥区别呢?CSS更加注重动画的展现,性能更好,而js的方式性能稍微差点,但是可以在动画执行的每一个过程中做些额外的操作。…...

金三银四,你准备好面试了吗? (附30w字软件测试面试题总结)

不知不觉,已是3月下旬。最近有很多小伙伴都在跟我谈论春招面试的问题,其实对于面试,我也没有太多的经验,只能默默地把之前整理的软件测试面试题分享给Ta。今天就来大致的梳理一下软件测试的面试体系(每一部分最后都有相…...

【C语言学习】数组

数组(Array)就是一些列具有相同类型的数据的集合,这些数据在内存中依次挨着存放,彼此之间没有缝隙。 数组不是C语言的专利,Java、C、C#、JavaScript、PHP 等其他编程语言也有数组。 C语言数组属于构造数据类型。一个…...

ElasticSearch序列 - SpringBoot整合ES:根据指定的 ids 查询

文章目录1. ElasticSearch 根据 ids 查询文档2. SpringBoot整合ES实现 ids 查询1. ElasticSearch 根据 ids 查询文档 ① 索引文档,构造数据 PUT /my_index/_doc/1 {"price":10 }PUT /my_index/_doc/2 {"price":20 }PUT /my_index/_doc/3 {&qu…...

Spark SQL实战(08)-整合Hive

1 整合原理及使用 Apache Spark 是一个快速、可扩展的分布式计算引擎,而 Hive 则是一个数据仓库工具,它提供了数据存储和查询功能。在 Spark 中使用 Hive 可以提高数据处理和查询的效率。 场景 历史原因积累下来的,很多数据原先是采用Hive…...

堆(数据结构系列11)

目录 前言: 1.优先级队列概念 2.堆的概念 3.堆的存储方式 4.堆的创建 5.创建堆的时间复杂度 6.堆的插入和删除 6.1堆的插入 6.2堆的删除 结束语: 前言: 上一次博客中小编主要与大家分享了 二叉树一些相关的知识点和一些练习题&…...

算法训练第四十二天|01背包问题 二维 、01背包问题 一维、416. 分割等和子集

动态规划part0401背包问题 二维01 背包二维dp数组01背包完整c测试代码总结01背包问题 一维一维dp数组(滚动数组)一维dp01背包完整C测试代码416. 分割等和子集题目描述思路01背包问题总结01背包问题 二维 视频链接:https://www.bilibili.com/…...

Java-如何使用Java将图片和文字拼接在一起(并非是给图片加水印)

之前有遇到一个问题 问题背景:项目中,有一个功能,管理端可以将客户创建的小程序码下载到本地,方便客户将对应门店的小程序码打印出来并张贴到门店,做门店的引流和会员入会。 具体问题:当小程序码的数量较少…...

Metasploit入门到高级【第三章】

来自公粽号:Kali与编程预计更新第一章:Metasploit 简介 Metasploit 是什么Metasploit 的历史和发展Metasploit 的组成部分 第二章:Kali Linux 入门 Kali Linux 简介Kali Linux 安装和配置常用命令和工具介绍 第三章:Metasploi…...

枚举的使用

Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。1 问题如何在类中使用枚举,例如枚举出一年的四个季度,并且通过迭代枚举…...

Python进阶语法

1.1 Python进阶语法 1.1.1 交换变量 一行代码快速交换两个变量&#xff0c;无需创建临时变量。 from icecream import ica 2 b 4 a, b b, a ic(a, b)ic| a: 4, b: 2 1.1.2 链式比较 from icecream import ica 97 if 90 < a < 100:ic(a)ic| a: 97 1.1.3 初始化列表…...

Pyspark_结构化流4

Pyspark 注&#xff1a;大家觉得博客好的话&#xff0c;别忘了点赞收藏呀&#xff0c;本人每周都会更新关于人工智能和大数据相关的内容&#xff0c;内容多为原创&#xff0c;Python Java Scala SQL 代码&#xff0c;CV NLP 推荐系统等&#xff0c;Spark Flink Kafka Hbase Hi…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

作为点的对象CenterNet论文阅读

摘要 检测器将图像中的物体表示为轴对齐的边界框。大多数成功的目标检测方法都会枚举几乎完整的潜在目标位置列表&#xff0c;并对每一个位置进行分类。这种做法既浪费又低效&#xff0c;并且需要额外的后处理。在本文中&#xff0c;我们采取了不同的方法。我们将物体建模为单…...

使用VMware克隆功能快速搭建集群

自己搭建的虚拟机&#xff0c;后续不管是学习java还是大数据&#xff0c;都需要集群&#xff0c;java需要分布式的微服务&#xff0c;大数据Hadoop的计算集群&#xff0c;如果从头开始搭建虚拟机会比较费时费力&#xff0c;这里分享一下如何使用克隆功能快速搭建一个集群 先把…...