Redis04-分布式锁

目录

Redis实现分布式锁

分布式锁的工作流程

Redis实现分布式锁

Redission的watch dog

Redis分布式锁的合理应用


Redis实现分布式锁

在单节点的服务器中,java中的synchronized机制是处于JVM层面的,只能保证线程之间的同步。而实际的服务部署中,我们通常会使用多节点的集群部署方式,而要保证多个节点中的不同进程对数据的同步操作,就需要使用分布式锁。

使用分布式锁的主要目的是在分布式环境中确保多个节点之间的协同操作,避免由于并发访问而导致的数据不一致、竞态条件等问题。以下是使用分布式锁的一些常见原因:

  1. 避免并发问题: 在分布式系统中,多个节点可能同时对共享资源进行访问。使用分布式锁可以确保对关键资源的访问在同一时刻只有一个节点拥有,避免并发问题,如数据不一致、丢失更新等。

  2. 保护共享资源: 分布式系统中的共享资源,例如数据库、缓存、文件等,可能同时被多个节点访问。通过使用分布式锁,可以保护这些共享资源,确保在任何时刻只有一个节点能够修改它们。

  3. 防止死锁: 在分布式系统中,由于网络分区、节点故障等原因,可能发生死锁。通过使用分布式锁,可以避免因为多节点间的协同操作导致的死锁问题。

  4. 控制访问顺序: 在某些场景下,需要对共享资源的访问进行有序控制,确保一些操作的执行顺序。分布式锁可以用于实现对资源的顺序访问。

  5. 实现分布式协调: 分布式锁是实现分布式协调和同步的一种重要机制。例如,在分布式任务调度、分布式事务等场景中,分布式锁可以用于协调不同节点的操作。

  6. 防止重复执行: 在一些需要幂等性操作的场景下,分布式锁可以用于防止同一操作被重复执行。

  7. 避免“多写”问题: 当多个节点同时写入同一数据时,可能导致“多写”问题,即最后写入的值覆盖了之前的写入。分布式锁可以用于保护写入操作,确保只有一个节点能够写入。

分布式锁的工作流程

Redis实现分布式锁

Redis实现分布式锁主要利用的是Redis的setnx命令。setnx是Set if no exists的简写。

CenOs7:0>setnx lock 1 # 首次设置lock值1
"1"  # 设置成功返回1
CenOs7:0>setnx lock 1 # lock已存在,给lock赋值
"0"  # 设置失败返回0,不做任何操作
CenOs7:0>get lock # 获取lock的值
"1"  # lock值为1
CenOs7:0>del lock # 删除lock,释放锁
"1"  # 删除成功,返回1
CenOs7:0>get lock # 获取lock的值
null # lock为空
CenOs7:0>setnx lock 1 # 设置lock值为1
"1"  # 设置成功

需要注意的是,setnx的方式是不支持重入锁的。而且锁的持有时间很难控制。单纯地依赖expire设置过期时间是不现实的。

Redission的watch dog

Redission引入了“看门狗”的机制,目的是处理锁的续期问题。

代码示例:

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
​
import java.util.concurrent.TimeUnit;
​
public class RedissonWatchdogExample {
​public static void main(String[] args) throws InterruptedException {// 创建 Redisson 客户端Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379");RedissonClient redisson = Redisson.create(config);
​// 获取分布式锁RLock lock = redisson.getLock("myLock");
​try {// 尝试获取锁并设置锁的过期时间为10秒// boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS);// 如果设置了第二个参数[锁的持续时间]就默认不使用watchdog// redission中的lock是依赖了底层lua脚本的原子性实现的boolean isLocked = lock.tryLock(10, TimeUnit.SECONDS);
​if (isLocked) {// 获取锁成功,执行业务逻辑System.out.println("Lock acquired. Executing business logic...");
​// 模拟业务逻辑执行时间Thread.sleep(5000);
​// 业务逻辑执行完毕,不需要手动释放锁,Watchdog会自动续期或者释放锁
​} else {System.out.println("Failed to acquire the lock within the specified time");}
​} finally {// 关闭 Redisson 客户端redisson.shutdown();}}
}

创建了一个名为"myLock"的分布式锁,并使用tryLock方法尝试获取锁,设置锁的过期时间为10秒。在获取锁成功后,执行了一段模拟的业务逻辑,并且无需手动释放锁,因为Watchdog会在锁过期时自动续期或释放锁。

Redission实现可重入锁

Redission通过Hash结构实现重入锁的,key对应的是lock,value存放的是线程信息。

需要注意的是,Redisson Watchdog是默认开启的,你不需要额外的配置。在正式的生产环境中,建议你根据实际需求进行更详细的配置,比如设置Watchdog的检查间隔、锁的失效时间等参数。

红锁(RedLock)

Redis集群是主从复制结构,Master负责写,Slave负责读。setnx是在Master实例上进行加锁。

  • Java应用通过setnx在Master节点获取锁。

  • Master节点异常,Redis通过哨兵机制选举出新的Master。

  • Java应用通过setnx在新的Master节点获取锁。

  • 此时集群中存在两把锁,违背了锁的互斥性。

针对这种情况,Redis提供了RedLock,它的主要机制是在(n/2+1)个节点实例上同时创建锁。

RedLock解决了锁的互斥性问题,同时缺点也很明显:实现复杂,性能差,同时运维繁琐。针对分布式中的CAP现象,不同的业务应该选择对应的方案:

  • AP思想(高可用性+分区容错):使用Redis实现分布式锁

  • CP思想(强一致性+分区容错):使用Zookeeper实现分布式锁

需要注意的是,Redisson Watchdog是默认开启的,你不需要额外的配置。在正式的生产环境中,建议你根据实际需求进行更详细的配置,比如设置Watchdog的检查间隔、锁的失效时间等参数。

Redis分布式锁的合理应用

Redis分布式锁是在多个节点之间实现互斥访问共享资源的一种机制。它可以应用于各种场景,以下是一些合理的应用场景:

  1. 分布式任务调度: 当有多个节点需要执行定时任务或者周期性任务时,可以使用分布式锁确保同一时刻只有一个节点在执行任务,避免重复执行或者竞态条件。

  2. 分布式缓存更新: 当多个节点需要同时更新某个缓存或者共享的数据时,可以使用分布式锁确保只有一个节点能够进行更新操作,防止并发问题。

  3. 分布式事务: 在分布式事务场景下,可能需要对一些关键资源进行加锁,以确保在事务执行期间,其他事务不会修改这些资源,从而保证事务的隔离性。

  4. 防止重复操作: 在一些场景下,可能需要防止某个操作被重复执行。通过使用分布式锁,可以确保同一时刻只有一个节点能够执行这个操作,防止重复操作。

  5. 分布式限流: 在某些情况下,需要对请求进行限流,确保系统不被过度请求。通过使用分布式锁,可以控制某个时间窗口内只有一个节点能够处理请求,实现简单的限流效果。

  6. 分布式协同: 当多个节点需要协同工作时,可以使用分布式锁确保各个节点之间的操作按照规定的顺序进行,防止不一致或混乱的情况发生。

  7. 分布式任务队列: 在分布式环境中,多个节点可能需要消费同一个任务队列。通过使用分布式锁,可以确保只有一个节点能够成功获取并消费队列中的任务,避免重复消费。

  8. 资源竞争: 当多个节点需要竞争某个资源时,可以使用分布式锁来进行竞争,确保只有一个节点能够成功占用资源,如分布式锁用于实现分布式秒杀场景。

需要注意的是,在使用分布式锁时,要注意锁的超时策略、锁的释放等问题,以确保系统的稳定性和性能。此外,选择成熟的分布式锁实现库,如Redisson、Curator等,可以减少潜在的问题,提高开发效率。

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

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

相关文章

Spark SQL编程

1. Spark SQL概述 1.1 什么是Spark SQL Spark SQL是用于结构化数据处理的Spark模块。与基本的Spark RDD API不同,Spark SQL提供的接口为Spark提供了有关数据结构和正在执行的计算的更多信息。在内部,Spark SQL使用这些额外的信息来执行额外的优化。与Spa…

解析SQL 获取表、字段及SQL查询参数

解析SQL 获取表、字段及SQL查询参数 1. 执行效果2. 使用2.1 引入依赖2.2 相关实体2.3 工具类 1. 执行效果 2. 使用 2.1 引入依赖 <!-- sql 解析处理--><dependency><groupId>com.github.jsqlparser</groupId><artifactId>jsqlparser</artifa…

「实用场景教程」如何用日程控件DHTMLX Scheduler制作酒店预订日历?(一)

dhtmlxScheduler是一个类似于Google日历的JavaScript日程安排控件&#xff0c;日历事件通过Ajax动态加载&#xff0c;支持通过拖放功能调整事件日期和时间&#xff0c;事件可以按天&#xff0c;周&#xff0c;月三个种视图显示。 DHTMLX Scheduler正式版下载 在本教程中&…

K8S的基础知识

K8S的意义与入门 专有名词 容器:包含了运行一个应用程序所需要的所有东西,包括:代码、运行时、各种依赖和配置。pod:K8s调度的最小单元,包含一个或多个容器。一个容器组中的容器具有紧密耦合性,共享资源,存储空间和IP。即同一个容器组中的容器可以通过localhost:xxx访问…

windows系统pycharm程序通过urllib下载权重https报错解决

报错内容&#xff1a; raise URLError(unknown url type: %s % type) urllib.error.URLError: <urlopen error unknown url type: https> 解决办法记录&#xff1a; 1. 下载 pyopenssl : pip install pyopenssl 此时&#xff0c; import ssl 可以通过提示指导你安…

简单地聊一聊Spring Boot的构架

前言 本文小编将详细解析Spring Boot框架&#xff0c;并通过代码举例说明每个层的作用。我们将深入探讨Spring Boot的整体架构&#xff0c;包括展示层、业务逻辑层和数据访问层。通过这些例子&#xff0c;读者将更加清晰地了解每个层在应用程序中的具体作用。通过代码实例&…

Uniapp开发 购物商城源码 在线电商商城源码 适配移动终端项目及各小程序

lilishop电商商城系统 商城移动端&#xff0c;使用Uniapp开发&#xff0c;可编译为所有移动终端项目及各小程序 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/88487579 源码下载2&#xff1a;关注我留言

0基础学习VR全景平台篇第121篇:认识视频剪辑软件Premiere

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 大家好&#xff0c;这节课是带领大家认识认识我们的剪辑软件Premiere&#xff0c;一般简称是PR。 &#xff08;PR界面&#xff09; 我们首先打开PR&#xff0c;第一步就是要创建…

深入理解JVM虚拟机第二十五篇:详解JVM方法的绑定机制静态绑定和动态绑定,早期绑定晚期绑定,并编写代码从字节码角度证明这件事情

大神链接&#xff1a;作者有幸结识技术大神孙哥为好友&#xff0c;获益匪浅。现在把孙哥视频分享给大家。 孙哥链接&#xff1a;孙哥个人主页 作者简介&#xff1a;一个颜值99分&#xff0c;只比孙哥差一点的程序员 本专栏简介&#xff1a;话不多说&#xff0c;让我们一起干翻J…

Android WebView专题

WebView 专题 第一个WebView程序&#xff1a;加载远程网址 Layout添加WebView组件&#xff1b; <WebViewandroid:id"id/webView_first"android:layout_width"match_parent"android:layout_height"match_parent"/>初始化组件&#xff0c;加…

arm2 day6

串口实现单个字符的收发 main.c uart4.c uart4.h

java轮播图接口实现

一. 内容简介 实现java后端用户管理接口&#xff0c;数据库使用msyql。 二. 软件环境 2.1 java 1.8 2.2 mysql Ver 8.0.13 for Win64 on x86_64 (MySQL Community Server - GPL) 2.3 IDEA ULTIMATE 2019.3 2.4d代码地址 https://gitee.com/JJW_1601897441/competitionAs…

【左程云算法全讲10】打表技巧和矩阵处理技巧

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招面试的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于左程云算法课程进行的&#xff0c;每个知识点的修正和深入主要参考…

冲击900亿美元估值!邀约路演、秘密交表的Shein上市有望

双十一的狂欢刚刚结束&#xff0c;Shein即将赴美上市的消息又在电商圈里投下一枚重磅炸弹。 继被媒体曝光其寻求900亿美金估值后&#xff0c;最新的消息称其已邀请投资人参与路演&#xff0c;且已秘密完成交表。这个神秘的中国独角兽&#xff0c;离敲钟登陆美股的日子越来越近…

SoftwareTest6 - 用 Selenium 怎么点点点

用 Selenium 来点点点 一 . 什么是自动化 ?1.1 自动化测试的分类接口自动化测试UI 自动化测试 (界面测试) 1.2 实现自动化测试的工具 : selenium环境部署驱动 二 . selenium 的使用2.1 一个简单的示例 : 让谷歌浏览器在百度首页搜索蔡徐坤准备工作编写代码 2.2 打开谷歌浏览器…

【vue】AntDV组件库中a-upload实现文件上传:

文章目录 一、文档&#xff1a;二、使用(以Jeecg为例)&#xff1a;【1】template&#xff1a;【2】script&#xff1a; 三、效果图&#xff1a; 一、文档&#xff1a; Upload 上传–Ant Design Vue 二、使用(以Jeecg为例)&#xff1a; 【1】template&#xff1a; <a-uploa…

day08_子网划分与子网掩码

什么是子网划分? 1、概念&#xff1a;借主机位给网络位使用,以此来达到把一个大网段划分为n个儿子网段的目的&#xff0c;2. 为何要进行子网划分&#xff1f;3、子网掩码&#xff1a;就是对ip地址打记号4、 网络地址的计算机方式&#xff1a;ip地址与子网掩码都转换成二进制&a…

基于51单片机PCF8591数字电压表数码管显示设计( proteus仿真+程序+设计报告+讲解视频)

PCF8591数字电压表数码管显示 1.主要功能&#xff1a;讲解视频&#xff1a;2.仿真3. 程序代码4. 设计报告5. 设计资料内容清单&&下载链接资料下载链接&#xff08;可点击&#xff09;&#xff1a; 基于51单片机PCF8591数字电压表数码管设计( proteus仿真程序设计报告讲…

Vue3-TypeScript-Threejs:导入外部的glb格式3D模型

一、直接上代码&#xff0c;在vue3-typescript-threejs 项目 导入外部的glb格式3D模型 极简代码&#xff0c;快速理解 <template><div ref"container"></div></template><script lang"ts" setup>import { onMounted, ref …

IEEE--DSConv: Efficient Convolution Operator 论文翻译

论文地址:https://arxiv.org/pdf/1901.01928v1.pdf 目录 摘要 1 介绍 2 相关工作 3 DSConv层 4 量化过程 5 分布偏移 6 优化推断 7 训练 8 结果 8.1 ImageNet 8.2 内存和计算负载 8.3 转移性 9 结论 摘要 我们引入了一种卷积层的变体&#xff0c;称为DSConv&…