Redis 分布式锁的实现方式
一般来说,在对数据进行“加锁”时,程序首先需要通过获取(acquire)锁来得到对数据排他性访问的能力,然后才能对数据执行一系列操作,最后还要将锁释放(release)给其他程序。
对于能够被多个线程访问的共享内存数据结构(shared-memory data structure)来说,这种“先获取锁,然后执行操作,最后释放锁”的动作非常常见。Redis 使用 WATCH 命令来代替对数据进行加锁,因为 WATCH 只会在数据被其他客户端抢先修改了的情况下,才通知执行了这个命令的客户端,而不会阻止其他客户端对数据进行修改,所以被称为乐观锁(optimistic lock)。
分布式锁也有类似的“首先获取锁,然后执行操作,最后释放锁”动作,但这种锁既不是给同一个进程中的多个线程使用,也不是给同一台机器上的多个进程使用,而是由不同机器上的不同 Redis 客户端进行获取和释放的。何时使用以及是否使用 WATCH 或者锁取决于给定的应用程序:有的应用不需要使用锁就可以正确地运行,而有的应用只需要使用少量的锁,还有的应用需要在每个步骤都使用锁。
分布式锁在业务中非常常见,能够避免在分布式环境中同时对同一个数据进行操作,进而避免并发问题。
锁出现不正确行为的原因,以及锁在不正确运行时的症状
- 持有锁的进程因为操作时间过长而导致锁被自动释放,但进程本身并不知晓这一点,甚至还可能会错误地释放掉了其他进程持有的锁
- 一个持有锁并打算执行长时间操作的进程已经崩溃,但其他想要获取锁的进程并不知道哪个进程持有锁,也无法检测出持有锁的进程已经崩溃,只能白白地浪费时间,等待锁被释放
- 在一个进程持有的锁过期后,其他多个进程同时尝试去获取锁,并且都获得了锁
- 上面提到的第一种情况和第三种情况同时出现,导致有多个进程获得了锁,并且每个进程都以为自己是唯一一个获得锁的
以下代码省去了一些程序的上下文环境描述。
// io-redis获取redis所有key
async getKeys(match, count = 100) {const { app: { redis }, ctx: { helper: { _ } } } = this;let keys = [];const scanStream = await redis.scanStream({ match, count });const result = await new Promise(resolve => {scanStream.on('data', data => {keys = keys.concat(data);});scanStream.on('end', () => {resolve(_.uniq(keys));});});return result;
}
// 获取redis所有key
async getKeys(pattern, count = 100) {const { app: { redis }, ctx: { helper: { _ } } } = this;let result = [];const _getKeys = async (cursor = 0) => {// redis scan迭代获取, 默认取100const apiResult = await redis.scan(cursor, 'match', pattern, 'count', count);result = result.concat(apiResult[1]);// 新游标返回0则表示迭代已结束if (Number(apiResult[0]) === 0) {return;}// 继续迭代await _getKeys(apiResult[0]);}await _getKeys();// 去重return _.uniq(result);
}
// redis获取锁
async lock(key, count) {const { app: { redis }, config: { cacheKey } } = this;const result = await redis.set(key, count, 'EX', cacheKey.lock.expireTime, 'NX');return result === 'OK';
}// redis释放锁
async unlock(key, count) {const { app: { redis } } = this;const script = `ifredis.call('get', KEYS[1]) == ARGV[1]thenreturn redis.call('del', KEYS[1])elsereturn 0end`;const result = await redis.eval(script, 1, key, count);return Boolean(result);
}
相关文章:
Redis 分布式锁的实现方式
一般来说,在对数据进行“加锁”时,程序首先需要通过获取(acquire)锁来得到对数据排他性访问的能力,然后才能对数据执行一系列操作,最后还要将锁释放(release)给其他程序。 对于能够…...
VMware上搭建的虚拟机突然本地无法连接服务器
长时间没有使用VMware 虚拟机了,今天突然登录上去,启动虚拟服务器后发现本地等不了了, 经过排查发现是开启了:VirtualBox Host-Only Network 关闭之后就本机就可以直连服务器了...
JDBC回顾
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 JDBC回顾 前言一、JDBC1.JDBC是什么?2.如何使用?(1)注册驱动(2)获取连接(3)操作…...
mq 消息队列 mqtt emqx ActiveMQ RabbitMQ RocketMQ
省流: 十几年前,淘宝的notify,借鉴ActiveMQ。京东的ActiveMQ集群几百台,后面改成JMQ。 Linkedin的kafka,因为是scala,国内很多人不熟。淘宝的人把kafka用java写了一遍,取名metaq,后…...
沃尔玛卖家必看!解决订单被Kan、Feng号问题的终极方案!
近期有很多沃尔玛卖家和工作室联系到我提到说在沃尔玛平台上下单,买家号出现副款义常订单被k掉,是什么原因、我们该如何去解决呢? 以下是一些可能导至你的测评订单被k单的原因: 1.技术问题:有时,网站或系…...
浅谈日常使用的 Docker 底层原理-三大底座
适合的读者,对Docker有过简单了解的朋友,想要进一步了解Docker容器的朋友。 前言 回想我这两年,一直都是在使用 Docker,看过的视频、拜读过的博客,大都是在介绍 Docker 的由来、使用、优点和发展趋势,但对…...
前端面试:【DOM】编织网页的魔法
嘿,亲爱的代码魔法师!在JavaScript的奇幻世界里,有一项强大的技能,那就是DOM操作。DOM(文档对象模型)操作允许你选择、修改和创建网页元素,就像是在编织一个魔法的网页。 1. 什么是DOMÿ…...
基于MATLAB开发AUTOSAR软件应用层Code mapping专题-part 2 Inport和Outports 标签页介绍
上篇我们介绍了Function页的内容,这篇我们介绍Inports和Outports页的内容,这里我们再次强调一个概念,code mapping是以simulink的角度去看的,就是先要在模型中建立simulink模块,在code mapping里映射他要对应的autosar的元素,之后生成代码时的c语言的名字是以Autosar的元…...
第9步---MySQL的索引和存储引擎
第9步---MySQL的索引和存储引擎 1.索引 1.1分类 索引可以快速的找出具有特定值的行。不用从头开始进行寻找了。 类别 hash和btree hash 根据字段值生生成一个hash的值 快速的进行定位到对应的行的值 可能会出现相同的值,找到对应的空间会出现对应的值 btree树…...
Numpy入门(3)—线性代数
线性代数 线性代数(如矩阵乘法、矩阵分解、行列式以及其他方阵数学等)是任何数组库的重要组成部分,NumPy中实现了线性代数中常用的各种操作,并形成了numpy.linalg线性代数相关的模块。本节主要介绍如下函数: diag&am…...
php的openssl_encrypt是不是自动做了PKCS5Padding?
在PHP中,openssl_encrypt函数默认使用的是PKCS7填充(不是PKCS5填充)。PKCS7填充实际上是PKCS5填充的扩展,用于对不同块大小的数据进行填充。 当你使用openssl_encrypt函数进行加密时,如果你没有显式指定填充模式和填充…...
在本地创建repository及上传至github
文章目录 本地管理设定git的用户名与邮箱初始化添加修改提交修改设定分支问题一:error: insufficient permission for adding an object... 数据同步创建SSH keys创建并关联远程仓库上传改动至github问题二:Failed to connect to github.com port 443: Connection timed out问题…...
情人节特别定制:多种语言编写动态爱心网页(附完整代码)
写在前面案例1:HTML Three.js库案例2:HTML CSS JavaScript案例3:Python环境 Flask框架结语 写在前面 随着七夕节的临近,许多人都在寻找独特而令人难忘的方式来表达爱意。在这个数字时代,结合创意和技术࿰…...
Docker mysql主从同步安装
1. 构建master实例 docker run -p 3307:3306 --name mysql-master \ -v /mydata/mysql-master/log:/var/log/mysql \ -v /mydata/mysql-master/data:/var/lib/mysql \ -v /mydata/mysql-master/conf:/etc/mysql \ -e MYSQL_ROOT_PASSWORDroot \ -d mysql:5.7 2. 构建master配置…...
docker update 命令
docker update 更新一个或多个容器的配置。官方文档 用法 $ docker update [OPTIONS] CONTAINER [CONTAINER...]请参阅选项部分OPTIONS,了解此命令可用的概述。 描述 该docker update命令动态更新容器配置。您可以使用此命令来防止容器消耗 Docker 主机的过多资…...
阻塞和挂起的区别和联系
阻塞和挂起是进程两种不同的状态,其描述如下: 阻塞:正在执行的进程由于发生某时间(如I/O请求、申请缓冲区失败等)暂时无法继续执行。此时引起进程调度,OS把处理机分配给另一个就绪进程,而让受阻…...
水力发电厂测量装置配置选型及厂用电管理系统
《水力发电厂测量装置配置设计规范》对水电厂的测量装置配置做了详细要求和指导。测量装置是水力发电厂运行监测的重要环节,水电厂的测量主要分为电气量测量和非电量测量。电气测量指使用电的方式对电气实时参数进行测量,包括电流、电压、频率、功率因数…...
【RabbitMQ】RabbitMQ整合SpringBoot案例
文章目录 1、前情提要【RabbitMQ】2、RabbitMQ-SpringBoot案例 -fanout模式2.1 实现架构总览2.2 具体实现2.2.1生产者2.2.1消费者 1、前情提要【RabbitMQ】 【RabbitMQ】消息队列-RabbitMQ篇章 RabbitMQ实现流程 2、RabbitMQ-SpringBoot案例 -fanout模式 2.1 实现架构总览…...
如何在window下cmd窗口执行linux指令?
1.Git:https://git-scm.com/downloads(官网地址) 2.根据自己的实际路径,添加两个环境变量 3.重启电脑...
c++基础系列:字符串、向量和数组
字符串、向量和数组 命名空间的using声明 目前用到的库函数基本上都属于命名空间std;通过using声明(using declaration)实现更简单的途径使用到命名空间中的成员。 标准库类型string string表示可变长的字符序列,必须先包含st…...
Python通达信数据获取终极指南:如何免费获取A股市场数据
Python通达信数据获取终极指南:如何免费获取A股市场数据 【免费下载链接】mootdx 通达信数据读取的一个简便使用封装 项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx 还在为金融数据分析而烦恼数据源问题吗?每次想要分析A股市场数据&a…...
NotebookLM PDF解析失效?3步精准定位文档结构断层并重建语义锚点
更多请点击: https://intelliparadigm.com 第一章:NotebookLM PDF解析失效的本质归因 NotebookLM 在处理某些 PDF 文档时出现“无法提取文本”或“内容为空”的现象,并非偶然的前端报错,而是源于底层 PDF 解析链路中多个关键环节…...
RustClaw:构建私有化AI助手,实现数据主权与本地化部署
1. 项目概述:打造你自己的数据主权AI助手 最近在折腾一个挺有意思的项目,叫RustClaw。简单来说,这是一个用Rust写的、跑在Discord上的AI助手机器人。但和那些把对话记录全扔给云端的聊天机器人不同,它的核心设计理念是 “数据主权…...
Oracle 迁移 PostgreSQL 踩坑:ROWNUM 与 DISTINCT 执行顺序差异导致 SQL 结果不一致
文章目录引言:一次诡异的"数据丢失"排查一、现象复现:同样的 SQL,不同的结果在 KES / Oracle 中的执行过程在 PostgreSQL 中的执行过程二、原理剖析:执行优先级的致命差异2.1 KES / Oracle:ROWNUM 的"先…...
深入Logos FPGA的PCB布局:如何针对FBG256、FBG484和LPG封装优化你的设计
深入Logos FPGA的PCB布局:如何针对FBG256、FBG484和LPG封装优化你的设计 在硬件设计领域,FPGA的PCB布局一直是工程师面临的核心挑战之一。特别是当项目需要在性能、成本和尺寸之间寻找平衡点时,封装选择往往成为决定成败的关键因素。Logos系列…...
株洲彩钢板厂家
彩钢板 彩色涂层钢板 以冷轧/镀锌钢板为基材,表面脱脂、磷化后,辊涂彩色有机涂层(聚酯、氟碳等),再烘烤成型。二、主要分类(3大类)1. 彩钢压型板(单板/彩钢瓦)• 结构&a…...
如何快速搭建Sunshine游戏串流服务器:终极自托管指南
如何快速搭建Sunshine游戏串流服务器:终极自托管指南 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 想要在任何设备上畅玩PC游戏吗?Sunshine开源游戏串流服…...
跨工具技能同步:构建统一操作习惯的中间层架构与实践
1. 项目概述:一个跨工具技能同步的构想在数字工具爆炸式增长的今天,我们每个人几乎都活在一个“工具丛林”里。作为一名长期与各种生产力工具、开发环境、设计软件打交道的从业者,我深刻体会到一种割裂感:在A工具里熟练无比的快捷…...
本地AI智能体框架NagaAgent:基于开源大模型的规划与工具调用实践
1. 项目概述:一个被低估的本地AI智能体框架最近在折腾本地大模型应用,特别是想搞点能自己跑起来的智能体(Agent),发现了一个挺有意思但讨论度不高的项目——RTGS2017/NagaAgent。乍一看这个标题,可能会觉得…...
嵌入式实战:STM32智能温度控制系统的算法优化与工程实现
嵌入式实战:STM32智能温度控制系统的算法优化与工程实现 【免费下载链接】STM32 项目地址: https://gitcode.com/gh_mirrors/stm322/STM32 在工业自动化、医疗设备和智能家居领域,温度控制系统的精度和稳定性直接影响着设备性能和用户体验。传统…...
