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

Redis-分布式锁!

分布式锁,顾名思义,分布式锁就是分布式场景下的锁,比如多台不同机器上的进程,去竞争同一项资源,就是分布式锁。

分布式锁特性

互斥性:锁的目的是获取资源的使用权,所以只让一个竞争者持有锁,这一点要尽可能保证;

安全性:避免锁因为异常永远不被释放。当一个竞争者在持有锁期间内,由于意外崩溃而导致未能主动解锁,其持有的锁也能够被兜底释放,并保证后续其它竞争者也能加锁;

对称性:同一个锁,加锁和解锁必须是同一个竞争者。不能把其他竞争者持有的锁给释放了。

可靠性:需要有一定程度的异常处理能力、容灾能力。
 

分布式锁的实现

 

1.直接用Redis的setnx命令

首先,当然是搭建一个最简单的实现方式, 直接用Redis的setnx命令, 这个命令的语法是: setnx key value如果key不存在,则会将key设置为value,并返回1;如果key存在,不会有任务影响,返回0。
基于这个特性,我们就可以用setnx实现加锁的目的:通过setnx加锁,加锁之后其他服务无法加锁,用完之后,再通过delete解锁

就是这个获取锁的过程就是setnx的过程 如果有锁了 那就会返回0 如果没锁 就会把key设置为value然后释放锁就会delete

2.支持过期时间

最简化版本有一个问题:如果获取锁的服务挂掉了,那么锁就一直得不到释放,就像石沉大海,查无音信。所以,我们需要一个超时来兜底。
Redis中有expire命令,用来设置一个key的超时时间。 但是setnx和expire不具备 原子性,如果setnx获取锁之后,服务挂掉(还没来的及设置时间),依旧是泥牛入海。
很自然,我们会想到,set和expire, 有没有原子操作?
当然有,Redis早就考虑到了这种场景,推出了如下执行语句: set key value nx ex seconds nx表示具备setnx特定,ex表示增加了过期时间,最后一个参数就是过期时间的值。

他把set和expire合成了一个原子操作

这个过期和释放锁是并列的 就是主动释放锁和过期都会delete

3.加上Owner

我们来试想一下如下场景:服务A获取了锁,由于业务流程比较长,或者网络延迟、GC卡顿等原因,导致锁过期,而业务还会继续进行。这时候,业务B已经拿到了锁,准备去执行,这个时候服务A恢复过来并做完了业务,就会释放锁,而B却还在继续执行。
在真实的分布式场景中,可能存在几十个竞争者,那么上述情况发生概率就很高,导致同一份资源频繁被不同竞争者同时访问,分布式锁也就失去了意义
基于这个场景,我们可以发现,问题关键在于,竞争者可以释放其他人的锁。(也就是说 只能这个锁持有者自己释放了锁才行 就是这个delete过程 只能自己来删除 而不能其他线程删除)那么在异常情况下,就会出现问题,所以我们可以进一步给出解决方案: 分布式锁需要满足谁申请谁释放原则,不能释放别人的锁,也就是说,分布式锁,是要有归属的。

我们获取锁之前不是会有一个delete释放锁的过程吗? 我们让其他线程没法执行这个delete操作 只有我锁持有者可以delete

具体步骤 释放前先检测是否是持有者要delete 然后返回检查结果 然后再根据结果进行操作


4.引入LUA


释放前先检测是否是持有者要delete 然后返回检查结果 然后再根据结果进行操作

这三步不是原子的

我们来看 检测和返回结果之间的间隙

这个同时锁过期了 

检测 这锁过期释放了锁 且有其他客户端获取到了锁 然后返回结果  删除锁 

这个时候 已经判断完了它是自己的锁 他就会删除这个锁

这就造成了锁的误删

然后LUA给这仨操作合成原子操作了

(其实owner )

分布式锁的可靠性靠什么保证

主从容灾

emmm 就是主库寄了 用从库顶一顶先

但是主从切换,需要人工参与,会提高人力成本。不过Redis已经有成熟的解决方案,也就是哨兵模式,可以灵活自动切换,不再需要人工介入。

一堆箭头乱七八糟的 描述一下 每个哨兵会监视其他两个哨兵的 同时还会监视主库和两个从库 

通过增加从节点的方式,虽然一定程度解决了单点的容灾问题,但并不是尽善尽美的,由于同步有时延,Slave可能会损失掉部分数据,分布式锁可能失效,这就会发生短暂的多机获取到执行权限。

更妥善的方法

多机部署

如果对一致性的要求高一些, 可以尝试多机部署,比如Redis的RedLock, 大概的思路就是多个机器,通常是奇数个,达到一半以上同意加锁才算加锁成功,这样,可靠性会向ETCD靠近。
现在假设有5个Redis主节点,基本保证它们不会同时宕掉,获取锁和释放锁的过程中,客户端会执行以下操作:
1.向5个Redis申请加锁;
2.只要超过一半,也就是3个Redis返回成功,那么就是获取到了锁。如果超过一半失败, 需要向每个Redis发送解锁命令;
3.由于向5个Redis发送请求,会有一定时耗,所以锁剩余持有时间,需要减去请求时间。这个可以作为判断依据,如果剩余时间已经为0,那么也是获取锁失败:
4.使用完成之后,向5个Redis发送解锁请求。
这种模式的好处在于,如果挂了2台Redis,整个集群还是可用的,给了运维更多时间来修复。

(这种方法太重了 业务很少会用的到)

 

分布式系统三大困境

简称NPC

这种模式的好处在于,如果挂了2台Redis,整个集群还是可用的,给了运维更多时间来修复。
另外,多说一句,单点Redis的所有手段,这种多机模式都可以使用,比如为每个节点配置哨兵模式,由于加锁是
-半以上同意就成功,那么如果单个节点进行了主从切换,单个节点数据的丢失,就不会让锁失效了。这样增强了
可靠性。
N:Network Delay (网络延迟)当分布式锁获得返回包的时间过长,此时可能虽然加锁成功,但是已经时过境迁,锁可能很快过期。RedLock算 了做了些考量,也就是前面所说的锁剩余持有时间,需要减去请求时间,如此一来,就可以一定程度解决网络延迟的问题。
P: Process Pause (进程暂停)比如发生GC,获取锁之后GC了,处于GC执行中,然后锁超时。其他锁获取,这种情况几乎无解。这时候GC回来了,那么两个进程就获取到了同一个分布式锁。

也许你会说,在GC回来之后,可以再去查一次啊?
这里有两个问题,首先你怎么知道GC回来了?这个可以在做业务之前,通过时间,进行一个粗略判断,但也是很吃场景经验的;第二,如果你判断的时候是ok的,但是判断完GC了呢?这点RedLock是无法解决的。
 

C: Clock Drift (时钟漂移)
如果竞争者A,获得了RedLock,在5台分布式机器上都加上锁。为了方便分析,我们直接假设5台机器都发生了时钟漂移,锁瞬间过期了。这时候竞争者B拿到了锁,此时A和B拿到了相同的执行权限。
根据上述的分析.可以看出,RedLock也不能扛住NPC的挑战,因此,单单从分布式锁本身出发,完全可靠是不可能的。要实现一个相对可靠的分布式锁机制,还是需要和业务的配合,业务本身要幂等可重入,这样的设计可以省却很多麻烦。
 

相关文章:

Redis-分布式锁!

分布式锁,顾名思义,分布式锁就是分布式场景下的锁,比如多台不同机器上的进程,去竞争同一项资源,就是分布式锁。 分布式锁特性 互斥性:锁的目的是获取资源的使用权,所以只让一个竞争者持有锁,这…...

Unity如何把游戏导出成手机安装包

文章目录 前言使用环境步骤添加场景构建APK 前言 本文章主要演示了,如何将制作好的游戏,导出成APK,安装到手机上。 使用环境 Unity2022。 步骤 首先打开你的项目,然后选择菜单栏的“File” > “Build Settings…”&#xf…...

使用爱校对软件保证公文材料质量的关键步骤

在日常的公文处理中,保证材料质量是每个企业和机构都追求的目标。而要实现这个目标,使用正确的工具是关键。爱校对软件正是这样一款专业的校对工具,它可以帮助我们保证公文材料的质量。接下来,让我们一起来看看使用爱校对软件保证…...

Spring Data Elasticsearch 的简单使用

目录 一、简介 二、配置 三、映射 四、 常用方法 五、操作(重点) 1、对索引表的操作 2、对文档的操作(重点) (1)、添加文档 (2)、删除文档 (3)、查询…...

2024」预备研究生mem-角平分线定理中线定理垂线定理、射影定理

一、角平分线定理 二、中线定理 三、垂线定理、射影定理 垂线定理 射影定理: 四、课后题...

nginx部署时http接口正常,ws接口404

可以这么配置 map $http_upgrade $connection_upgrade {default upgrade; close; }upstream wsbackend{server ip1:port1;server ip2:port2;keepalive 1000; }server {listen 20038;location /{ proxy_http_version 1.1;proxy_pass http://wsbackend;proxy_redirect off;proxy…...

数学建模的概念和学习方法(什么是数学建模)

一、初步认识数学建模 数学建模是将数学方法和技巧应用于实际问题的过程。它涉及使用数学模型来描述和分析现实世界中的现象、系统或过程,并通过数学分析和计算来预测、优化或解决问题。数学建模可以应用于各种领域,包括自然科学、工程、经济学、环境科学…...

ChatGPT在智能安全监测和入侵检测中的应用如何?

ChatGPT在智能安全监测和入侵检测领域具有潜在的应用价值。虽然ChatGPT主要是一个基于自然语言处理的模型,但结合其他技术和领域专业知识,它可以用于生成和分析文本数据,提供实时安全警报、威胁情报等,从而在安全监测和入侵检测方…...

智能数据建模软件DTEmpower 2023R2新版本功能介绍

DTEmpower是由天洑软件自主研发的一款通用的智能数据建模软件,致力于帮助工程师及工科专业学生,利用工业领域中的仿真、试验、测量等各类数据进行挖掘分析,建立高质量的数据模型,实现快速设计评估、实时仿真预测、系统参数预警、设…...

BDA初级分析——认识SQL,认识基础语法

一、认识SQL SQL作为实用技能,热度高、应用广泛 在对数据分析人员的调查中SQL长期作为热度排名第-一的编程语言超过Python和R SQL:易学易用,高效强大的语言 SQL:Structured Query Language 结构化查询语言 SQL:易学…...

Qt应用开发(基础篇)——MDI窗口 QMdiArea QMdiSubWindow

一、前言 QMdiArea类继承于QAbstractScrollArea,QAbstractScrollArea继承于QFrame,是Qt用来显示MDI窗口的部件。 滚屏区域基类 QAbstractScrollAreahttps://blog.csdn.net/u014491932/article/details/132245486 框架类 QFramehttps://blog.csdn.net/u01…...

图片转换成pdf格式?这几种转换格式方法了解一下

图片转换成pdf格式?将图片转换成PDF格式的好处有很多。首先,PDF格式具有通用性,可以在几乎任何设备上查看。其次,PDF格式可以更好地保护文件,防止被篡改或者复制。此外,PDF格式还可以更好地压缩文件大小&am…...

thingsboard编译安装踩坑记录

thingsboard编译安装踩坑记录 一、编译:二、运行 朋友的thingsboard没人维护,要装新的服务器,啥文档也没有,就让参考官网的文档,版本也比较老3.2.2的,拿过来试了试记录下踩坑的地方。 一、编译:…...

汇编语言例子集合

本人早酷爱汇编语言,曾经以自己能直接执行和操作机器码而自豪不已。下面列出一些电脑隐藏角落里的汇编语言例子程序。后续发现整理后会进一步添加完善。 汇编语言在windows上的bmp文件浏览器。 使用win32汇编编写。 下载地址:https://download.csdn.net/…...

强化学习:用Python训练一个简单的机器人

一、介绍 强化学习(RL)是一个令人兴奋的研究领域,它使机器能够通过与环境的交互来学习。在这篇博客中,我们将深入到RL的世界,并探索如何使用Python训练一个简单的机器人。在本文结束时,您将对 RL 概念有基本…...

【Docker】Docker使用之容器技术发展史

🎬 博客主页:博主链接 🎥 本文由 M malloc 原创,首发于 CSDN🙉 🎄 学习专栏推荐:LeetCode刷题集 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正&#xff0…...

postgresql的在windows下的安装

postgresql的在windows下的安装 下载安装步骤超级用户设置密码本地化设置安装信息安装完成 查看postgresql服务pgAdmin的使用打开命令 行工具查询数据库版本 创建数据库 下载 官网地址 https://www.postgresql.org/ 下载页面 https://www.postgresql.org/download/ windows下…...

python 自动化学习(四) pyppeteer 浏览器操作自动化

背景 之前我在工作中涉及到了很多地方都是重复性的页面点点点工作,又因为安全保密原则不开放接口和数据库,只有一个页面来提供点击进行操作,就想着用前面学的自动化来实现,但发现前面学的模拟操作对浏览器来说并没有那么友好&…...

P1009 阶乘之和

[NOIP1998 普及组] 阶乘之和 题目描述 用高精度计算出 S 1 ! 2 ! 3 ! ⋯ n ! S 1! 2! 3! \cdots n! S1!2!3!⋯n!( n ≤ 50 n \le 50 n≤50)。 其中 ! 表示阶乘,定义为 n ! n ( n − 1 ) ( n − 2 ) ⋯ 1 n!n\times (n-1)…...

Linux内核源码剖析之TCP保活机制(KeepAlive)

写在前面: 版本信息: Linux内核2.6.24(大部分centos、ubuntu应该都在3.1。但是2.6的版本比较稳定,后续版本本质变化也不是很大) ipv4 协议 https://blog.csdn.net/ComplexMaze/article/details/124201088 本文使用案例…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

Python Einops库:深度学习中的张量操作革命

Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...

ZYNQ学习记录FPGA(一)ZYNQ简介

一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...

JS红宝书笔记 - 3.3 变量

要定义变量,可以使用var操作符,后跟变量名 ES实现变量初始化,因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符,可以创建一个全局变量 如果需要定义…...