redis之作为分布式锁使用

news2024/11/18 19:56:31

写在前面

本文一起看下redis作为分布式锁使用的相关内容。

1:怎么算是锁或没锁

锁和没锁本身其实就是用一个变量的值来表示,比如变量lock,当值为1时代表处于上锁状态,当值为0时表示没有锁,那么多线程想要获取锁的话就是判断当前lock值是否为0,如果是的话则将其设置为1,则代表该线程获取到了锁,释放锁的过程就是将lock的设置为0。当然,基本原理就是这样,实际中可能略有不同。伪代码可能如下:

在这里插入图片描述

接下来我们分别从基于单实例redis和多实例redis两种情况来看下如何加锁。

1.1:单实例redis

我们前面分析了,加锁其实就是对一个变量赋予特定值,成功则是加锁成功,否则则是加锁失败,还有就是,这个过程必须是原子的,我们也知道,redis中的原子操作有两种,第一种是单命令,第二种是lua脚本,我们先看第一种,redis提供了命令setnx ,该命令的行为是如果是key不存在,则设置,否则什么也不做,如下:

127.0.0.1:6379> setnx aaaaa bbbb
(integer) 1
127.0.0.1:6379> setnx aaaaa bbbb
(integer) 0

可以看到再次调用就返回0了。因此可以使用其来实现加锁的操作,其实这样还是不够的,因为缺少释放锁的操作,释放也很简单,只需要执行del 但是此时可能存在如下2个问题:

1:如果最终del没有执行成功,则锁将会一直不能释放
2:执行del的线程不一定是加锁的线程,如线程A加锁了,但是线程B执行了del,但此时线程A还没有执行完毕,线程C又拿到了锁,就会出现问题了

对于1,可以通过expire 命令来设置过期时间,对于2,我们可以给每个客户端分配特有的值,进行设置,即setnx key val中的val每个客户端都是不一样的,在进行删除的时候,判断当前是否为自己加的锁,是才del,否则不操作,为了保证原子性,我们需要使用lua脚本来实现这个锁的过程:

// local key = KEYS[1]
// local val = redis.call("GET", key);
// 其中ARGV[1]代表的是客户端设置的值,只有当前值是自己设置的时候才执行删除key操作
if redis.call("GET", KEYS[1]) == ARGV[1]
then
        redis.call('del', KEYS[1])
        return 1
else
        return 0
end 

其实,以上对于问题1,还需要单独再执行一个命令expire,这显然会影响到程序的性能,对于这点,我们可以使用set命令来完成,不存在才设置值以及同时设置过期时间,该命令格式如下:

set key value [EX seconds] [PX milliseconds] [NX|XX] 

其中NX用来设置当key不存在时才设置,PX用来设置过期的时长,此时加锁代码可能如下:

127.0.0.1:6379> set lock:key client_val NX PX 10000
OK

即10秒后过期并删除。解锁lua脚本可能如下:

local key = KEYS[1]
local val = redis.call("GET", key);

// 其中ARGV[1]代表的是客户端设置的值,只有当前值是自己设置的时候才执行删除key操作
if val == ARGV[1]
then
        redis.call('del', KEYS[1])
        return 1
else
        return 0
end 

其实和使用setnx命令的解锁方式是一样的。单实例锁的问题是,一旦实例宕机,就没有办法加锁和解锁了,应用程序也就无法正常运行了。

1.2:多实例redis锁

因为是多个实例同时操作,所以加锁过程一定要遵循一定的规范和过程,redlock分布式锁算法就描述了这样的一个规范和过程,该算法如下:

1:记录当前系统的时间
2:使用set k v NX PX millisec 完成加锁
3:所有实例加锁完成后,按照如下条件判断是否加锁成功
    3.1:是否超过半数的实例加锁成功
    3.2:当前时间减去第一步记录的加锁开始时间是否超过了锁的超时时间,没超过则成功

释放锁的过程和单实例类似,只不过需要每个实例上都执行释放锁的lua脚本。

写在后面

参考文章列表:

Redlock:Redis分布式锁最牛逼的实现 。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/81151.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【网络工程】8、实操-万达酒店综合项目(二)

接上篇《7、实操-万达酒店综合项目(一)》 之前我们讲解了酒店网络项目的整体需求文档,包括项目背景、总体架构设计以及网络功能域划分、配置标准、路由规划等。本篇我们就来按照项目要求进行模拟拓扑的构建实操。 一、总体架构效果 按照之前…

力扣 1827. 最少操作使数组递增

题目 给你一个整数数组 nums (下标从 0 开始)。每一次操作中,你可以选择数组中一个元素,并将它增加 1 。 比方说,如果 nums [1,2,3] ,你可以选择增加 nums[1] 得到 nums [1,3,3] 。 请你返回使 nums 严…

2.10.0 以太网 传统STP生成树简介、STP工作方式简单介绍

2.10.0 以太网 传统STP生成树(简介、工作方式) 作用: STP(Spanning Tree Prortoco)生成树协议,它的出现解决了交换机网络环路的问题。 交换机网络中收到BUM帧的时候,将会进行泛洪的操作&…

HCIA 以太网的帧

一、前言 网络经常会遇到一些词汇,比如包、报文、帧,其概念如下: 1)帧(frame):数据链路层的协议数据单元,它包括三部分:帧头、数据部分、帧尾。其中,帧头和…

vector容器模拟实现(上)

1.1:模板设置 因为不能与库已经有的vector冲突,首先定义命名空间namespace my 使用类模板。 1.2:成员变量 vector有size,capacity,同时也要进行扩容操作和缩容(shrink to fit)操作,所以需要3个迭代器。 p…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java杨柳农贸市场摊位管理系统qr3ri

大四计算机专业的同学们即将面临大学4年的最后一次考验--毕业设计。通过完成毕业设计来对过去4年的大学学习生活做一个总结,也是检验我们学习成果的一种方式,毕业设计作品也是我们将来面试找工作的一个敲门砖。 选题前先看看自己掌握哪些技术点、擅长哪…

mysql首次安装error 1045 28000解决

mysql首次安装error 1045 28000解决 首先找到了这个教程,按其操作一步一步来,发现到登录输入密码这一步,怎么样都报错 2021MySql-8.0.26安装详细教程(保姆级) 然后按照这篇操作,但还是不行 MySQL安装1045错…

[附源码]Python计算机毕业设计Djangoospringboot作业管理系统

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…

通过窗口看世界之 界面制作如此简单-带你制作旅游观光系统界面-----效果图展示

👨‍💻个人主页:元宇宙-秩沅 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 秩沅 原创 收录于专栏 玩归玩闹归闹,别拿java开玩笑 ⭐旅游管理系统部分效果图展示⭐ 文章目录⭐旅游管理系统部分效果图…

持久化的配置都不知道,也敢说精通Redis?

前言 所谓持久化可以简单理解为将内存中的数据保存到硬盘上存储的过程。持久化之后的数据在系统重启或者宕机之后依然可以进行访问,保证了数据的安全性。一键获取最先java文档。 Redis有两种持久化方案,一种是快照方式(SNAPSHOTTING&#xff…

前端 | 前端设计设计及代码收集

全部来源于Github,侵权删! 1.Maxime Euzire 2.Shubham Singh | Resume 3.Natasha Theodora Petrus 4.Ana Mara Martnez Gmez 5.bagussona.github.io 6.leodevbro.github.io 7.yuanlinping.github.io 8.Dr.Q 9.sureshmurali.github.io 10.Chandrika Deb | Software…

常见的接口测试面试题

1、按你的理解,软件接口是什么? 答: 就是指程序中具体负责在不同模块之间传输或接受数据的并做处理的类或者函数。 2、HTTP和HTTPS协议区别? 答: https协议需要到CA(Certificate Authority,证…

[附源码]JAVA毕业设计医疗器械销售电子商城(系统+LW)

[附源码]JAVA毕业设计医疗器械销售电子商城(系统LW) 项目运行 环境项配置: Jdk1.8 Tomcat8.5 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目…

Spring:Ioc

目录 一、Spring的两大核心机制 1、IOC/ DI:控制反转和依赖注入 2、AOP:面向切面编程 二、IOC/ DI:控制反转 / 依赖注入: 1、bean的基础配置: 2、bean的实例化 3、配置bean 4、依赖注入方式 三、注解开发定义bean 注解依赖注入 Spring设计理念 …

Spring推断构造方法源码深度解析

文章目录前言思考目标一、bean的实例化入口-createBeanInstance1、源码逻辑思路**核心点,主要做了几件事情**2、instantiateBean-默认无参实例化3、instantiate-实例化4、instantiateClass-实例化类二、获取构造函数候选数组-determineConstructorsFromBeanPostProc…

这十套练习,教你如何用Pandas做数据分析(04)

练习4-Apply函数 探索1960 - 2014 美国犯罪数据 步骤1 导入必要的库 运行以下代码 import numpy as np import pandas as pd 步骤2 从以下地址导入数据集 运行以下代码 path4 ‘…/input/pandas_exercise/pandas_exercise/exercise_data/US_Crime_Rates_1960_2014.csv’…

微信小程序|入门进阶

接下来点击新建项目就可以在主界面中预览到我们的豆瓣电影示例了 小程序开发初体验 Hello world 希望是一个从零到一的转换过程~ 创建项目 接下来创建一个新的项目,理解小程序项目的基本结构和一些基础语法。 官方的开发工具为此准备了一个QuickStart项目。在创建过程中,…

利用jrebel与arthas在centos7 springboot热部署

jrebel 热部署 jrebel在本地是可以class xml一起热部署,但是远程热部署xml不行,所以用arthas代替去热部署xml 1.jrebel 反向代理 因为jrebel是收费插件,所以要高一些小动作咱们才能‘正常’使用,当然你也可以拿别人代理好的操作…

并发基础(五):ThreadPoolExecutor源码解析

尺有所短,寸有所长;不忘初心,方得始终。 请关注公众号:星河之码 在JDK提供的几种线程池技术,除了JDK8新加的newWorkStealingPool之外,其余的几种线程池都是通过ThreadPoolExecutor 来实现线程池技术&#x…

本周大新闻|FDA公布XR认证医疗名单,索尼推数字孪生平台Mapray

本周大新闻,AR方面,苹果首款MR头显或推迟至2023年下半年发布;FDA官网公布经过认真的AR/VR医疗方案名单;索尼预测AR/VR光学发展路径;索尼公布3D数字孪生平台Mapray;索尼公布ToF AR SDK。 VR方面&#xff0c…