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

关于redis中的分布式锁

目录

分布式锁的基础实现

引入过期时间

引入校验id

引入lua脚本

引入看门狗

redlock算法


分布式锁的基础实现

多个线程并发执行的时候,执行的先后顺序是不确定的,需要保证程序在任意执行顺序下,执行逻辑都是ok的。

在分布式系统中,每个服务器都是独立的进程,因此,之前的锁,就难以对现在分布式系统中的多个进程之间产生制约。分布式系统中,多个进程之间的执行顺序也是不确定的。

像这样的情况就需要引入分布式锁来解决上述问题。

举个例⼦: 考虑买票的场景, 现在⻋站提供了若⼲个⻋次, 每个⻋次的票数都是固定的。现在存在多个服务器节点, 都可能需要处理这个买票的逻辑: 先查询指定⻋次的余票, 如果余票 > 0, 则设置余票值 -= 1。

显然上述的场景是存在 "线程安全" 问题的, 需要使⽤锁来控制。否则就可能出现 "超卖" 的情况。

此时如何进⾏加锁呢? 我们可以在上述架构中引⼊⼀个 Redis ,作为分布式锁的管理器。给其他的服务器提供“加锁”这样的服务。(redis是一种典型的可以用来实现分布式锁的方案,但不是唯一一种)

买票服务器,在进行买票的过程中,就需要先加锁(往redis上设置一个特殊的key-value)。完成上述买票操作之后,再把这个key-value删除掉。

其他服务器买票的时候,也要去redis上设置key-value,如果发现key-value已经存在,就认为“加锁失败”。(放弃/阻塞,就看具体的实现策略了)

上述操作就可以保证,第一个服务器执行“查询 ->更新”过程中,第二个服务器不会执行“查询”。

引入过期时间

如果服务器直接掉电,进程异常终止,这样的情况会导致redis上设置的key无人删除,也就导致其他服务器无法获取到锁了。这种情况该如何处理?

可以给key设置过期时间,一旦时间到,key就会自动被删除掉了。

可以通过 set ex nx 命令来实现。

比如设置key的过期时间为1000ms,那么意味着即使出现极端情况,某个服务器挂了,没有正确释放锁,这个锁最多保持1000ms,也就会自动释放了。

引入校验id

所谓的加锁,就是给redis上设置一个key-value。

所谓的解锁,就是给redis上这个key-value删除掉。

是否可能出现服务器1执行了加锁,服务器2执行了解锁

有可能的。服务器有可能不小心执行到了解锁操作,因此就可能进一步给整个系统带来更严重的问题。

为了解决上述问题,就需要引入校验机制

1.给服务器编号,每个服务器有一个自己的身份标识

2.进行加锁的时候,设置key-value,key对应着要针对哪个资源加锁(比如车次),value就可以存储刚才服务器的编号。表示出当前这个锁是哪个服务器加上的。

3.后续在解锁的时候,就可以进行校验了。(解锁的时候,先查询一下这个锁对应的服务器编号。然后判定一下这个编号是否就是当前解锁的服务器的编号,如果是,才能真正执行del。如果不是,就失败)

引入lua脚本

在解锁的时候,先查询判定,再进行del。此处两步操作(不是原子的),就可能会出现问题。

一个服务器内部,也可能是多线程的。此时,就可能同一个服务器,两个线程都在执行上述解锁操作。

在线程A执行完DEL之后,B执行DEL之前。服务器2的线程C正好要执行加锁(set),此时由于A已经把锁释放了,C的加锁是能够成功的。因为在线程B查询判定的时候,redis服务器已经判定这次请求来源于一个服务器了。但是紧接着,线程B DEL 就到来了。就把刚刚服务器2的加锁操作给解锁了。

可以使用lua脚本来解决上述问题。

可以使用lua编写一些逻辑,把这个脚本上传到redis服务器上。然后就可以让客户端来控制redis执行上述脚本了。

redis执行脚本的过程,也是原子的。相当于执行一条命令一样。

使⽤ Lua 脚本完成上述解锁功能:

if redis.call('get',KEYS[1]) == ARGV[1] thenreturn redis.call('del',KEYS[1])
elsereturn 0
end;

引入看门狗

在加锁的时候,key的过期时间设定多长合适?

如果设置的短,可能在你的业务还执行完,就释放锁了。如果设置的太长,也会导致"锁释放不及时"问题。

更好的方式,是“动态续约”。初始情况下,设置一个过期时间(比如1s)就提前在还剩300ms(不一定,可以灵活调整)的时候,如果当前任务还没执行完,就把过期时间再续1s。等到时间又快到了,任务还没执行完,就再续。

如果服务器,中途崩溃了,自然就没人负责续约了,此时,锁就能在较短的时间内被自动释放。

动态续约这样的行为往往需要一个专门的线程,负责续约这个事情。称为“看门狗”。

redlock算法

使用redis作为分布式锁,redis本身有没有可能挂了呢? 当然有可能。

要想保证“高可用”就需要通过这样一系列的“预案演习”。

进行加锁,就是把key设置到主节点上,如果主节点挂了,有哨兵自动的把从节点升级成主节点,进一步的保证刚才的锁仍然可用。

但是主节点和从节点之间的数据同步,是存在延时的。可能主节点收到了set请求,还没来得及同步给从节点,主节点就先挂了。即使从节点升级成了主节点。但是,刚才的加锁对应的数据,也是不存在的。

Redlock 算法:

引⼊⼀组 Redis 节点。其中每⼀组 Redis 节点都包含⼀个主节点和若⼲从节点. 并且组和组之间存
储的数据都是⼀致的,相互之间是 "备份" 关系。

此处加锁,就是按照一定的顺序,针对这些组redis都进行加锁操作。如果某个节点挂了,继续给下一个加锁即可。

如果写入key成功的节点个数超过总数的一半,就视为加锁成功。

同理,进行解锁的时候,也会把上述节点都设置一遍。

以上,关于redis的分布式锁,希望对你有所帮助。

相关文章:

关于redis中的分布式锁

目录 分布式锁的基础实现 引入过期时间 引入校验id 引入lua脚本 引入看门狗 redlock算法 分布式锁的基础实现 多个线程并发执行的时候,执行的先后顺序是不确定的,需要保证程序在任意执行顺序下,执行逻辑都是ok的。 在分布式系统中&am…...

SQL Server数据库慢SQL调优

SQL Server中慢SQL会显著降低系统性能并引发级联效应。首先,用户直接体验响应时间延长,核心业务操作(如交易处理、报表生成)效率下降,导致客户满意度降低甚至业务中断。其次,资源利用率失衡,CPU…...

【css酷炫效果】实现鱼群游动动态效果

【css酷炫效果】实现小鱼游动动态效果 缘创作背景css代码创建div容器引入jquery引入鱼群js完整代码效果图成品资源下载链接:点击下载 缘 在开发系统功能的时候,无意间看到了小鱼游动特效,感觉很有意思,就在网上找了相关教程,分享给大家。 创作背景 刚看到csdn出活动了…...

kubectl describe pod 命令以及输出详情讲解

kubectl describe pod 命令格式 kubectl describe pod <pod-name> -n <namespace><pod-name>&#xff1a;Pod 的名称。 -n <namespace>&#xff1a;指定命名空间&#xff0c;默认是当前命名空间。 controlplane ~ ✖ kubectl describe pod newpods-d…...

Python实战(2)-数据库支持

使用简单的纯文本文件可实现的功能有限。诚然&#xff0c;使用它们可做很多事情&#xff0c;但有时可能还需要额外的功能。你可能希望能够自动完成序列化&#xff0c;此时可求助于shelve和pickle&#xff08;类似于shelve&#xff09;​。不过你可能需要比这更强大的功能。例如…...

Java面试黄金宝典4

1. 什么是泛型 &#xff1f;与 T 的区别 原理 泛型是 Java 编程语言中的一个强大特性&#xff0c;它提供了编译时类型安全检查机制&#xff0c;允许在定义类、接口和方法时使用类型参数。这些类型参数在使用时会被具体的类型所替代&#xff0c;从而实现代码的复用和类型安全。泛…...

从 Snowflake 到 Databend Cloud:全球游戏平台借助 Databend 实现实时数据处理

导读&#xff1a;某全球游戏平台为全球数百万玩家提供实时的技能型游戏体验与无缝的实时互动。对该游戏平台而言&#xff0c;保持数据的实时更新和实时分析&#xff0c;对提升玩家互动和留存率至关重要。他们在使用 Snowflake 进行实时数据摄取和分析时遇到了重大挑战&#xff…...

Docker搭建MySQL主从服务器

一、在主机上创建MySQL配置文件——my.cnf master服务器配置文件路径&#xff1a;/data/docker/containers/mysql-cluster-master/conf.d/my.cnf slave服务器配置文件路径&#xff1a; /data/docker/containers/mysql-cluster-master/conf.d/my.cnf master服务配置文件内容 …...

点击劫持详细透析

点击劫持&#xff08;Clickjacking&#xff09;是一种前端安全攻击手段&#xff0c;攻击者通过视觉欺骗诱导用户在不知情的情况下点击隐藏的页面元素&#xff0c;从而执行非预期的操作。以下是攻击过程的详细说明&#xff1a; 攻击过程步骤 攻击者构造恶意页面 创建一个恶意网页…...

C语言每日一练——day_12(最后一天)

引言 针对初学者&#xff0c;每日练习几个题&#xff0c;快速上手C语言。第十二天。&#xff08;最后一天&#xff0c;完结散花啦&#xff09; 采用在线OJ的形式 什么是在线OJ&#xff1f; 在线判题系统&#xff08;英语&#xff1a;Online Judge&#xff0c;缩写OJ&#xff0…...

10、STL中的unordered_map使用方法

一、了解 1、unordered_map(哈希) unordered_map是借用哈希表实现的关联容器。 访问键值对O&#xff08;1&#xff09;&#xff0c;最坏情况O&#xff08;n&#xff09;&#xff0c;例如哈希冲突严重时。【n是一个哈希桶的元素数量】 unordered_map特性 键值对存储&#xff…...

本地部署deepseek-r1建立向量知识库和知识库检索实践【代码】

目录 一、本地部署DS 二、建立本地知识库 1.安装python和必要的库 2.设置主目录工作区 3.编写文档解析脚本 4.构建向量数据库 三、基于DS,使用本地知识库检索 本地部署DS,其实非常简单,我写了一篇操作记录,我终于本地部署了DeepSeek-R1(图文全过程)-CSDN博客 安装…...

正则表达式引擎深入探讨

正则表达式引擎&#xff08;Regular Expression Engine&#xff09;是正则表达式得以“活起来”的核心。它是一个精密的软件组件&#xff0c;负责接收正则表达式和输入文本&#xff0c;解析模式并执行匹配或替换操作&#xff0c;最终输出结果——可能是简单的“是否匹配”&…...

监控视频联网平台在智慧水利中的应用

随着智慧城市建设的深入推进&#xff0c;智慧水利作为其中的重要组成部分&#xff0c;正逐步实现数字化、智能化和网络化转型。在这一过程中&#xff0c;监控视频联网平台凭借其高效的数据采集、传输与分析能力&#xff0c;成为智慧水利建设的关键技术支撑。以下是监控视频联网…...

深入解析素数筛法:从埃氏筛到欧拉筛的算法思想与实现

素数筛法是一种用于高效生成素数的算法。常见的素数筛法包括埃拉托斯特尼筛法&#xff08;埃氏筛&#xff09;和欧拉筛&#xff08;线性筛&#xff09;。下面我们将详细讲解这两种筛法的思想&#xff1a; 一、 埃拉托斯特尼筛法&#xff08;埃氏筛&#xff09; 思想&#xff1…...

关于前端指令

在前端开发中&#xff0c;指令&#xff08;Directives&#xff09;通常指在框架中使用的一种特殊的语法或机制&#xff0c;用于扩展 HTML 的功能。常见的指令主要存在于前端框架中&#xff0c;如 Vue.js、Angular 等。下面我们将分别介绍 Vue.js 和 Angular 中的常用指令&#…...

ubuntu20.04系统没有WiFi图标解决方案_安装Intel网卡驱动

文章目录 1. wifi网卡配置1.1 安装intel官方网卡驱动backport1.1.1 第四步可能会出现问题 1.2 ubuntu官方的驱动1.3 重启 1. wifi网卡配置 我的电脑是华硕天选4&#xff08;i7&#xff0c;4060&#xff09;&#xff0c;网卡型号intel ax201 ax211 ax210通用。 参考文章&#…...

蓝桥杯day2:解码异或 后的数组

一、题意 未知 整数数组 arr 由 n 个非负整数组成。 经编码后变为长度为 n - 1 的另一个整数数组 encoded &#xff0c;其中 encoded[i] arr[i] XOR arr[i 1] 。例如&#xff0c;arr [1,0,2,1] 经编码后得到 encoded [1,2,3] 。 给你编码后的数组 encoded 和原数组 arr …...

Vite+微前端Qiankun-状态管理

一、前言 在微前端架构中&#xff0c;状态管理是一个重要的课题。由于子应用是独立的&#xff0c;它们之间可能需要共享状态或通信。以下是基于qiankun微前端架构的状态管理方案&#xff0c;结合Vue 3和Vite的实现。 二、状态管理方案 在微前端中&#xff0c;状态管理可以分为…...

【初学者】Python语言中有没有指针类型?

李升伟 整理 在Python语言中&#xff0c;没有像C或C那样的显式指针类型。Python的设计哲学强调简洁和易读&#xff0c;因此它隐藏了许多底层的细节&#xff0c;包括指针。 不过&#xff0c;Python中的变量可以被视为对对象的引用。当你创建一个对象并将其赋值给一个变量时&am…...

网络编程---多客户端服务器

写一个服务器和两个客户端 运行服务器和2个客户端&#xff0c;实现聊天功能 客户端1 和 客户端2 进行聊天 客户端1将聊天数据发送给服务器 服务器将聊天数据转发给客户端2 要求&#xff1a; 服务器使用 select 模型实现 客户端1使用 poll 模型实现 客户端2使用 多线程实现…...

SPACE_GAME

以下是一些關於星際遊戲的 GitHub 代碼範本&#xff0c;您可以根據需求進行修改或擴展。這裡提供一個簡單的 Python 代碼範例&#xff0c;展示如何創建一個簡單的星際遊戲框架。 專案結構 space_game/ ├── main.py ├── spaceship.py ├── enemy.py └── README.md1…...

Web Component 教程(五):从 Lit-html 到 LitElement,简化组件开发

前言 在现代前端开发中&#xff0c;Web 组件是一种非常流行的技术&#xff0c;它允许我们创建可重用的、自包含的 UI 元素。而 Lit-html 是一个简洁高效库&#xff0c;用于在 Web 组件中进行渲染。在这篇教程中&#xff0c;我们一步步学习如何 Lit-html 来创建 Web Component。…...

Vue3:构建高效用户界面的利器

一、Vue.js 简介​ Vue.js&#xff08;读音 /vjuː/, 类似于 view&#xff09;是一套构建用户界面的渐进式框架。它只关注视图层&#xff0c;采用自底向上增量开发的设计。Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件 &#xff0c;学习起来非常简单…...

LeetCode 2614.对角线上的质数:遍历(质数判断)

【LetMeFly】2614.对角线上的质数&#xff1a;遍历(质数判断) 力扣题目链接&#xff1a;https://leetcode.cn/problems/prime-in-diagonal/ 给你一个下标从 0 开始的二维整数数组 nums 。 返回位于 nums 至少一条 对角线 上的最大 质数 。如果任一对角线上均不存在质数&…...

红日靶场(二)——个人笔记

靶场搭建 新增VMnet2网卡 **web&#xff1a;**需要配置两张网卡&#xff0c;分别是外网出访NAT模式和内网域环境仅主机模式下的VMnet2网卡。 **PC&#xff1a;**跟web一样&#xff0c;也是需要配置两张网卡&#xff0c;分别是外网出访NAT模式和内网域环境仅主机模式下的VMn…...

实时视频分析的破局之道:蓝耘 MaaS 如何与海螺 AI 视频实现高效协同

一、蓝耘 MaaS 平台&#xff1a;AI 模型全生命周期管理的智能引擎 蓝耘 MaaS&#xff08;Model-as-a-Service&#xff09;平台是由蓝耘科技推出的 AI 模型全生命周期管理平台&#xff0c;专注于为企业和开发者提供从模型训练、推理到部署的一站式解决方案。依托云原生架构、高…...

清晰易懂的 Swift 安装与配置教程

初学者也能看懂的 Swift 安装与配置教程 本教程将手把手教你如何在 macOS 系统上安装 Swift&#xff0c;配置依赖包缓存位置&#xff0c;并指出新手容易踩坑的细节。即使你是零基础小白&#xff0c;也能快速上手&#xff01; 一、安装 Swift&#xff08;macOS 环境&#xff09…...

大数据 ETL 异常值缺失值处理完整方案

在大数据时代,数据已成为推动业务创新与决策优化的重要资产。然而,数据的海量、异构及实时性往往伴随着噪声、错误记录以及缺失现象,严重影响下游分析模型的准确性和可靠性。尤其在 ETL(抽取、转换、加载)环节中,如何在海量数据流中迅速甄别并处理异常数据,便成为决定整…...

macOS homebrew - 切换源

https://mirrors.tuna.tsinghua.edu.cn/help/homebrew/ 环境变量中 添加&#xff1a; export HOMEBREW_BREW_GIT_REMOTE"https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git" export HOMEBREW_CORE_GIT_REMOTE"https://mirrors.tuna.tsinghua.edu.cn…...