浅谈redis分布式锁
浅谈redis分布式锁
分布式锁介绍
分布式锁,顾名思义,分布式系统中的锁,当多个进程不在同一个系统中时,用分布式锁控制各个进程对共享资源的访问,通过互斥来保持一致性。
使用场景:电商中某商品的秒杀活动,接口中的幂等性校验等
分布式锁的特性
(1)互斥性。锁的目的是获取共享资源的使用权,则需保证在并发情况下,同一时刻只有一个线程能获得锁
(2)加锁解锁对称性。线程使用加锁获得对共享资源的使用后,使用完毕必须解锁,即,加锁解锁需为同一个线程
(3)防止死锁。假如由系统等原因出现宕机情况导致线程获取到锁后来不及解锁,而其他线程无法获取到锁,此情况为死锁,避免此情况,有必要设置锁的有效时间,确保系统出故障,在超出锁的有效时间后其他线程能获取到锁。
(4)锁粒度尽量小。锁的颗粒度要尽量小,避免导致大量线程同时为获取同一个锁而造成阻塞
(5)可重入性。同一个线程在锁使用期间可以重复拿到同一个资源的锁。
常用的三种分布式锁
(1) 基于数据库表主键唯一性原理、排他锁实现分布式锁
(2) 基于ZK临时有序节点实现的分布式锁
(3) 基于redis中setnx命令的原子性实现的分布式锁
Redis分布式锁的阶段性进展
基于redis为目前最常见的锁及之前介绍的redis原理,简单介绍下redis分布式锁
实现一个简易的Redis分布式锁
阶段性1、利用redis的setnx和expire命令设置一个简单的redis锁,代码如下:
String thread = "thread";Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", thread,30, TimeUnit.SECONDS);if(lock){//(1)加锁成功,处理handle("此处执行业务逻辑");//(2)处理完毕后解锁Object lockValue = redisTemplate.opsForValue().get("lock");if(thread.equals(lockValue)){//根据值对比判断是此线程的锁后删除锁redisTemplate.delete("lock");// 删除锁}}else{// 加锁失败: 重试或者直接返回获取锁失败retryOrReturn();}
以上代码看着没什么问题,实现了针对某个线程获取锁,且设置超时时间,并且根据值对比判断,只能此线程解锁。然而,忽略一个问题,由于在获取锁并删除这个过程中并非原子性,假如线程A删除锁的时候,锁已超时,自动解锁,同时其他线程B获取到锁,此时A把B持有的锁给删除。
那么如何实现锁对比判断和删除是一个原子性呢?见阶段性2
引入LUA
阶段性2、引入LUA删除锁
引入LUA,在获取锁的value值,对比是否一致,假如相等则删除,此段过程保证其原子性。代码如下:
String lockKey = "lock";String thread = "thread";Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, thread,30, TimeUnit.SECONDS);if(lock){//(1)加锁成功,处理handle("此处执行业务逻辑");//(2)处理完毕后解锁Object lockValue = redisTemplate.opsForValue().get("lock");//LUA脚本String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";// 原子删除Object lock1 = redisTemplate.execute(new DefaultRedisScript<Integer>(script, Integer.class), Arrays.asList(lockKey, thread));}else{// 加锁失败: 重试或者直接返回获取锁失败retryOrReturn();}
框架Redission
以上结合redis+Lua的实现,在框架redission中均一实。Redission,在一个提供redis基础功能实现的情况下,还提供了一系列的分布式服务。从而使使用者的开发能够集中的专注于业务逻辑上。
除redission具备了锁的锁的互斥性和可重入性等基本功能,还增加了其他功能,比如引入Watch Dog解决了一个关于锁的自动续期问题,以及引入Red Lock增加了一些更安全的锁实现
简易代码如下:
RLock lock = redisson.getLock ("lock");//获取锁或阻塞等待lock.lock ();try {handle("此处执行业务逻辑");} finally {//释放锁,已封装获取到此线程的锁并封装lock.unlock ();}
看门狗(Watch Dog)
场景:假如线程A获取到锁后,由于执行的逻辑耗时比较长, 在运行期间超出了默认的超时时间(30s)范围。则出现在线程A未执行完毕正常释放锁的情况下,由超时解锁,线程B重新获取到锁,引发故障。
针对此场景,引入Redission的Watch Dog实现自动续期,保证在线程A使用期间,不会超时而引发其他多个线程同时持有锁的情况
原理:看门狗相当于是一个定时任务,线程一旦加锁成功,会对应启动一个看门狗(属于后台线程)。每10s观察线程是否还持有锁,如果有,则延迟锁的的持有时间,将时间重置到30s,直至线程主动解锁或者系统故障看门狗不执行
注意:如果指定超时时间,不会自动续签时间,此时需保证线程执行业务逻辑的时间务必大于指定超时时间。
关于红锁(RedLock)
场景:假设在集群中,有多个redis master节点,这些节点是完全独立的,其中一个master获取到锁后发生故障,此时还未来得及发生主从复制,即key未来得及同步到从节点上。而此时通过哨兵选举,其一slave节点升级为master节点。那么此时会出现,后续应用会申请到同一个锁,则此时同一个锁被获取了不只一次,导致出现问题。
针对以上情况,引入红锁,利用多个 Redission node 最终 组成 RedLock分布式锁,Redission node 是互相独立的,不存在任何复制或者其他隐含的分布式协调机制。解决主从结构下存在的安全问题。
RedLock特点:
加锁过程中,在一个redis集群中,依次从N个reidis节点上获取锁(需要相同的key和value),并且至少半数以上(N/2+1)的redis节点获取到锁,才算是获取锁成功,否则获取失败。红锁以节点组的方式解决单个节点出现故障的情况。
** 场景**:假设redis集群中五个主节点,客户端申请获取锁的请求到了redis节点(节点三个A\B\C获取到锁)并成功执行setnx操作,此时假如其中一节点A宕机,则返回给客户端的响应失败,在客户端层面看,是获取锁超时而失败,但是在redis集群看来是获取锁成功。然后客户端在释放锁时,也会对那些获取锁失败的redis节点发起同样的请求。
RedLock弊端:在加锁/解锁多个节点,其过程均耗费时间,性能较低。针对红锁,假如全部redis重启,也可能会出现锁失效的问题。
因此是否使用红锁,需结合实际场景使用
相关文章:
浅谈redis分布式锁
浅谈redis分布式锁 分布式锁介绍 分布式锁,顾名思义,分布式系统中的锁,当多个进程不在同一个系统中时,用分布式锁控制各个进程对共享资源的访问,通过互斥来保持一致性。 使用场景:电商中某商品的秒杀活动…...
【Python保姆级教程】List容器
文章目录 前言一、列表是什么二、列表的定义2.1 有初始值2.2 空列表使用方括号创建空列表使用list()函数创建空列表 三、list列表常用操作3.1 添加元素3.2 删除元素3.3 修改元素3.4 列表长度 四、遍历操作4.1 使用for循环4.2 使用while循环和索引 总结 前言 Python是一种广泛使…...
微服务保护-授权规则
个人名片: 博主:酒徒ᝰ. 个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来。 本篇励志:三人行,必有我师焉。 本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》,SpringCloud…...
v-if失效原因
一般v-if失效都是和绑定变量有关,我所知道的一般有两种 1.绑定的变量为String类型或者其他类型 就是返回的变量类型与所需要的布尔类型不匹配。 <template><div><div id"container" ref"container" v-iftype></div>&l…...
Chrome 基于 Wappalyzer 查看网站所用的前端技术栈
1. 找到谷歌商店 https://chrome.google.com/webstore/search/wappalyzer?utm_sourceext_app_menu 2. 搜索 Wappalyzer 3. 添加至Chrome 4. 使用 插件 比如打开 https://www.bilibili.com/ 就可以看到其所以用的前端技术栈了...
python的装饰器
作用:在不改变原来函数的代码情况下,进行修改,或者增加函数的功能装饰器本质上就是一个闭包雏形:def wrapper(fn): wrapper: 装饰器 , fn: 目标函数def inner():# 在目标函数执行前的一些动作fn()# 在目标函数执行后的一些动作return inner #千万别加(),这里是返回一…...
P2P协议的传输艺术
TP 采用两个 TCP 连接来传输一个文件。 控制连接:服务器以被动的方式,打开众所周知用于 FTP 的端口 21,客户端则主动发起连接。该连接将命令从客户端传给服务器,并传回服务器的应答。常用的命令有:list——获取文件目…...
辅助驾驶功能开发-功能规范篇(21)-4-XP行泊一体方案功能规范
XPilot Parking 自动泊车系统 • 超级自动泊车辅助(Super AutoParking Assist)、语音控制泊车辅助(Autoparking with Speech) - 产品定义 超级自动泊车辅助是⼀个增强的自动泊车辅助系统。在超级自动泊车辅助系统中,识别车位将会变得实时可见, 并且不可泊入的⻋位也将…...
家政服务小程序上门服务小程序预约上门服务维修保洁上门服务在线派单技师入口
套餐一:源码=1500元 套餐二:全包服务 包服务器+域名+认证小程序+搭建+售后=2000元 主要功能: 1、服务商入驻 支持个人或企业入驻成为平台服务商; 2、发布商品 入驻服务商后,可以发布服务商品,用户可以在线下单,预约服务; 3、发布需求 用户可以发布一口价或竞价需求…...
LeetCode精选100题-【3数之和】-2
这里写自定义目录标题 解法1:解法2: 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。注意:答案中不…...
springboot集成mybatis-plus
一、在spring boot中配置mybatis-plus 1、创建一个spring boot项目,注意勾选mysql 2、在pom.xml文件中添加mybatis-plus的依赖包 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0&qu…...
再想一想GPT
一 前言 花了大概两天时间看完《这就是ChatGPT》,触动还是挺大的,让我静下来,认真地想一想,是否真正理解了ChatGPT,又能给我们以什么样的启发。 二 思考 在工作和生活中,使用ChatGPT或文心一言,…...
Blazor前后端框架Known-V1.2.15
V1.2.15 Known是基于C#和Blazor开发的前后端分离快速开发框架,开箱即用,跨平台,一处代码,多处运行。 Gitee: https://gitee.com/known/KnownGithub:https://github.com/known/Known 概述 基于C#和Blazo…...
Tomcat 的部署和优化
目录 1、什么是Tomcat 1.1、静态页面的选择 2、Tomcat是怎么运行的 3、安装jdk & 部署jdk环境 & Tomcat 安装 1、安装jdk 2、配置jdk环境变量 3、tomcat安装 4、Tomcat启动 5.优化tomcat启动速度 6.Tomcat的主要命令 7.Tomcat 配置虚拟主机 8.Tomca…...
后端中间件安装与启动(Redis、Nginx、Nacos、Kafka)
后端中间件安装与启动 RedisNginxNacosKafka Redis 1.打开cmd终端,进入redis文件目录 2.输入redis-server.exe redis.windows.conf即可启动,不能关闭cmd窗口 (端口配置方式:redis目录下的redis.windows.conf配置文件,…...
【电子元件】常用电子元器件的识别之电阻器
目录 前言1. 电阻器的识别1.1 普通电阻器的识别1. 普通电阻器的识别色环电阻器绕线电阻器水泥电阻器贴片电阻器网络电阻器(排阻)保险电阻器精密电阻器2. 电阻器的符号3. 普通电阻器的主要参数标称阻值和允许误差额定功率最高工作电压温度系数1.2 电位器的识别1. 电位器的识别…...
指针和数组笔试题讲解(2)
🐵本篇文章将会对上篇一维数组笔试题的剩余部分和二维数组的笔试题进行讲解 一、一维数组 1>试题部分(一)✏️ char* p "abcdef";printf("%zd\n", sizeof(p)); printf("%zd\n", sizeof(p 1)); printf("%zd\n", sizeo…...
MapReduce YARN 的部署
1、部署说明 Hadoop HDFS分布式文件系统,我们会启动: NameNode进程作为管理节点DataNode进程作为工作节点SecondaryNamenode作为辅助 同理,Hadoop YARN分布式资源调度,会启动:ResourceManager进程作为管理节点NodeM…...
vue 引入zTree
下载js包解压后找个地方放文件夹内 引入 import "/common/zTree/js/jquery-1.4.4.min" import "/common/zTree/js/jquery.ztree.core.min.js" import "/common/zTree/js/jquery.ztree.excheck.min.js" import "/common/zTree/css/metroSt…...
链队列的基本操作(带头结点,不带头结点)
结构体 typedef struct linknode{int data;struct linknode* next;后继指针 }linknode; typedef struct {linknode* front, * rear;//队头队尾指针 }linkquene; 初始化队列(带头结点) int initquene(linkquene* q)//初始化队列 {q->front q->r…...
深入学习 Redis Cluster - 基于 Docker、DockerCompose 搭建 Redis 集群,处理故障、扩容方案
目录 一、基于 Docker、DockerCompose 搭建 Redis 集群 1.1、前言 1.2、编写 shell 脚本 1.3、执行 shell 脚本,创建集群配置文件 1.4、编写 docker-compose.yml 文件 1.5、启动容器 1.6、构建集群 1.7、使用集群 1.8、如果集群中,有节点挂了&am…...
C现代方法(第3、4章)笔记
文章目录 C现代方法笔记(chapter3&4)第3章 格式化输入/输出3.1 printf函数3.1.1 转换说明3.1.2 转义序列 3.2 scanf函数3.2.1 scanf函数的工作方法3.2.2 格式串中的普通字符3.2.3 易混淆的printf函数和scanf函数 问与答编程题 第4章 表达式4.1 算术运…...
R语言绘制染色体变异位置分布图,RIdeogram包
变异位点染色体分布图 今天分享的内容是通过RIdeogram包绘制染色体位点分布图,并介绍一种展示差异位点的方法。 在遗传学研究中,通过测序等方式获得了基因组上某些位置的基因型信息。 如下表,第一列是变异位点的ID,第二列是染色体…...
Vue知识系列(7)每天10个小知识点
目录 系列文章目录Vue知识系列(1)每天10个小知识点Vue知识系列(2)每天10个小知识点Vue知识系列(3)每天10个小知识点Vue知识系列(4)每天10个小知识点Vue知识系列(5&#x…...
5分钟就能实现的API监控,有什么理由不做呢?
API深度影响着你的应用 今天的数字应用世界其实是一个以API为中心的世界,我们只是没有意识到这些API的重要性。比如在电子商务交易、社交媒体等对交互高度依赖的领域,可以说API决定了应用的质量一点也不为过。 以京东为例,用户的每一次操作背…...
Jmeter引入外部jar包以满足加密数据的Post请求
目录 一、把项目打成jar包 1、创建一个Maven项目,并保证可以正常运行。 2、把工具类放置项目中,确保无报错且能够正常使用。 3、打包 4、验证 jar包是否有效 5、你想打多个工具类的包 二、在jmeter中使用 1、把jar包放到jmeter仓库下,…...
了解冒泡排序
package com.mypackage.array;import java.util.Arrays;public class Demo07 {public static void main(String[] args) {int[] a {3,2,6,7,4,5,6,34,56,7};int[] sort1 sort1(a); //调用我们自己写的排序方法后,返回一个排序后的数组System.out.println(Array…...
群辉 Synology NAS Docker 安装 RustDesk-server 自建服务器只要一个容器
from https://blog.zhjh.top/archives/M8nBI5tjcxQe31DhiXqxy 简介 之前按照网上的教程,rustdesk-server 需要安装两个容器,最近想升级下版本,发现有一个新镜像 rustdesk-server-s6 可以只安装一个容器。 The S6-overlay acts as a supervi…...
为什么要有override
多态一定会成功吗 因为逻辑是用户编写的,那么肯定会有遗漏的地方,那就要规则来限制。就比如多态,都知道条件之一是子类重写了父类的虚函数,但是如果子类没有严格遵守这个规则,就无法达到目的。就比如这个代码…...
Linux界的老古董
Slackware 是由 Patrick Volkerding 制作的 Linux 发行版,从 1993 年发布至今也一直在 Patrick 带领下进行维护。7 月 17 日,Slackware 才刚刚过完它 24 岁的生日,看似年纪轻轻的它,已然是 Linux 最古老的发行版。 Slackware 的发…...
网站如何设置二级域名/深圳外贸网络推广渠道
文章目录一、先说思路二、示例代码一、先说思路 1、使用cross-env修改系统常量,使程序知道接下来的操作要想那个服务器自动部署 2、使用ssh2操作服务器,将服务器上原有的项目改名,并放入记录文件夹 3、使用scp2将打包后的文件发送到对应的服…...
做视频网站每部电影都要版权/百度怎么提交收录
GroupBy是个Collector,它是用来进行Stream上的collect操作的。Collect是一个Mutable Reduction。所谓reduction,相当于把集合里的每一个元素依次带入一个函数,最终得到一个值。比如求一组int的和,可以用reduction写作。int sum n…...
给个网站免费的/永久免费无代码开发平台网站
我们知道RabbitMQ可以配置成Queue做主从复制(按照官方的说法叫配置mirror queue),对master queue的写操作会被复制到其他slave上去(也就是复制到mirror queue上去)。这对rabbitmq的这个特性,有些人会问这样…...
网站建设中的技术问题/余姚网站如何进行优化
%{ 1.这就是传说中的多行注释 2.成功! %} 注意是大括号哟...
安全者 wordpress/网络营销策略包括
前面文章介绍了前端路由简单实现和Pjax入门方面的文章,今天来分享一个单页面应用神器jquery.pjax.js。 HTML 我们准备一个加载div#loading,默认隐藏,ajax请求的时候才显示。#container是用来加载响应的页面内容。.pagination是分页条组件。 <div clas…...
星月教你做网站回顾文档/百度推广售后客服电话
***服务大家都知道,虚拟专用网络,今天我们就来说说怎么用linux搭建pptp *** 说实话,我这也算是第一次照着命令敲然后成功了的,最后才搞明白怎么回事,特贡献出来给大家,希望大家共同进步 系统环境: 2.6.18-9…...