Redis实现分布式锁源码分析

为什么使用分布式锁

单机环境并发时,使用synchronized或lock接口可以保证线程安全,但它们是jvm层面的锁,分布式环境并发时,100个并发的线程可能来自10个服务节点,那就是跨jvm了。

简单分布式锁实现

SETNX
格式:setnx key value
当且仅当key不存在时,key能设置成功并返回1,否则返回0。
SETNX即SET if Not eXists 如果不存在。

在这里插入图片描述

SETNX存在的问题

高并发场景下,有可能存在key自动过期了,加锁的线程还未执行完成的情况。此时线程2加锁进来了,且刚好线程1执行完了,线程1会把线程2刚刚创建的锁删掉,导致后面进来了更多的线程。【自己加的锁被别人删除了】

解决方案:给每个加锁的key生成一个唯一的UUID作为value,删除之前,从redis拿出来的UUID与当前线程一致才能删除key。
在这里插入图片描述
在这里插入图片描述
然而finally依然存在问题,因为释放锁的代码不是原子操作。【超时零界点】,在判断uuid相同后,且还未删除key前,此时key超时了,其他线程加锁成功,当前线程执行delete命令时,删除的依然是其他线程加的锁。

以上问题均是由于锁的时间不够长导致,接下来的解决方案是【锁续命】

锁续命

原理:线程1加锁成功后,再创建一个线程,使用定时任务来监控锁剩余时间。定时任务执行的周期必须小于锁的超时时间。比如锁超时时间默认设置为30秒,那么该线程每10秒执行一次,给锁重新设置超时时间为30秒, 保证主线程删除锁时,是自己加的锁。如果主线程已释放锁,子线程执行定时任务时会先判断主线程加的key是否还存在。 目前市面上已有成熟的解决方案,如redisson,它适用于分布式各种场景。参考redisson帮助文档

Redisson续命锁流程

在这里插入图片描述

引入redisson的依赖包

<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.27.2</version>
</dependency>  

创建一个Redisson的bean注册到Spring容器中

在这里插入图片描述

//获取锁对象
RLock redissonLock = redisson.getLock(lockKey);
//加分布式锁
redissonLock.lock();
........
//解锁
redissonLock.unlock(); 

Redisson加锁源码

底层是基于lua脚本实现,它能保证原子性。因为Redis服务端执行命令是单线程的,读到这一块lua代码会将它当成一个整体执行完,再去执行下一条命令。

第一步通过lua脚本加锁成后,返回null,加锁失败返回锁剩余时间
hset key field value 通过hash结构设置field为UUID+线程ID,value是1,表示重入次数。 key是构建锁时传入的redisson.getLock(lockKey); 锁超时时间默认是30秒。
在这里插入图片描述

第二步:看门狗机制给锁续命
Future模式异步执行lua脚本加锁,加锁成功后回调Future的监听器获取加锁结果。 加锁的lua脚本执行成功后返回null,则进入scheduleExpireRenewal()方法定时的给锁重置超时时间。
在这里插入图片描述
创建一个TimeTask延时任务,10秒后才执行run()方法,lua脚本判断锁存在则重设锁的超时时间为30秒。它同样是使用的Future模式,下面添加了一个监听,重置结束后,会回调监听器,监听器拿到结果再回调scheduleExpireRenewal()方法本身。
在这里插入图片描述
在这里插入图片描述

第三步:加锁失败的线程自旋等待

  1. 加锁失败后,先订阅该key的channel通道消息,类似于一个队列或topic,当锁在过期之前释放了,需要唤醒等待的线程竞争锁。
  2. 进入while(true)自旋加锁。先尝试一次加锁,成功则退出循环,失败则获取Semaphore调用tryAcquire()等待ttl秒后,重新进入while(true)尝试获取锁。如果1000个线程同时结束等待,就会一起抢锁,所以该锁是非公平锁
    在这里插入图片描述
    在这里插入图片描述
    第四步:释放锁时,发布该key的channel消息,通知等待的线程竞争锁。
    一旦channel中有消息后,会执行LockPubSub.onMessage()方法,获取一个Semaphora信号量释放等待的线程,让他们竞争锁。
    在这里插入图片描述
    在这里插入图片描述

总结:redisson的架构设计涉及到Future自旋锁看门狗机制发布订阅lua脚本semaphore等技术。
它的lock()接口实现的是非公平锁。tryAcquire()加锁成功后,继续执行业务代码。其他线程拿锁时返回锁剩余的时间ttl,判断ttl大于0,则使用Semaphore.getLatch().tryAcquire(),等到超时时间结束后再去抢锁。如果ttl还没有变为0,此时锁已释放,主线程会向指定的channel发送一条消息,等待的线程会订阅这个消息LockPubSub.onMessage(),拿到释放锁的消息后调用Semaphore.getLatch().release(),唤醒阻塞的线程立刻抢锁。
主线程给锁续命使用的是Future机制,异步开启了一个线程,每隔10秒嵌套调用重设锁时间的方法。

lua脚本

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

【ollama】linux、window系统更改模型存放位置,全网首发2024!

首先是window系统 so easy 直接进入系统环境变量添加就行 其次是linux系统 全靠自己试出来的,去Ollama官网找半天文档不知道在哪,而且linux也没有说:【 https://github.com/ollama/ollama/blob/main/docs/README.md https://github.com/ollama/ollama/blob/main/docs/li…

最大异或对(trie树)

题目描述&#xff1a; 思路&#xff1a; 1、首先此题我们要知道异或的规则&#xff0c;这里不赘述了&#xff0c;可以百度 2、如果利用trie树去找到一个数字与其异或能得到最大值 比如二进制数&#xff1a;1010.....是一个很大的数 我们想要异或得到的值更大&#xff0c;就需…

HarmonyOS(二十)——管理应用拥有的状态之LocalStorage(页面级UI状态存储)

LocalStorage是页面级的UI状态存储&#xff0c;通过Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage也可以在UIAbility实例内&#xff0c;在页面间共享状态。 本文仅介绍LocalStorage使用场景和相关的装饰器&#xff1a;LocalStorageProp和LocalS…

微服务技术栈之rabbitMQ高级(二)

我们该如何确保MQ消息的可靠性&#xff1f; 如果真的发送失败&#xff0c;有没有其它的兜底方案&#xff1f; 这些问题&#xff0c;在这一次的学习中都会找到答案。 生产者的可靠性 首先&#xff0c;我们一起分析一下消息丢失的可能性有哪些。 消息从发送者发送消息&#…

StarRocks实战——云览科技存算分离实践

目录 背景 一、平台现状&痛点 1.1 使用组件多&#xff0c;维护成本高 1.2 链路冗长&#xff0c;数据时效性难以保证 1.3 服务稳定性不足 二、StarRocks 存算分离调研 2.1 性能对比 2.2 易用性 2.3 存储成本 三、StarRocks 存算分离实践 3.1 查询优化 3.1.1 物化…

Linux网络编程: 以太网帧Frame/ARP/RARP详解

一、TCP/IP五层模型 物理层&#xff08;Physical Layer&#xff09;&#xff1a;物理层是最底层&#xff0c;负责传输比特流&#xff08;bitstream&#xff09;以及物理介质的传输方式。它定义了如何在物理媒介上传输原始的比特流&#xff0c;例如通过电缆、光纤或无线传输等。…

【论文阅读】Diffused Heads: Diffusion Models Beat GANs on Talking-Face Generation

Diffused Heads: 扩散模型在说话人脸生成方面击败GANs paper&#xff1a;[2301.03396] Diffused Heads: Diffusion Models Beat GANs on Talking-Face Generation (arxiv.org) code&#xff1a;MStypulkowski/diffused-heads: Official repository for Diffused Heads: Diffu…

R:简易的Circos图

library(grid) library(circlize) library(RColorBrewer) library(ComplexHeatmap) setwd("C:/Users/fordata/Downloads/Circos") # 创建颜色调色板 coul <- colorRampPalette(brewer.pal(9, "Set3"))(12) # 读取基因组数据 genome <- read.table(ci…

贪心算法(两个实例)

例一&#xff1a;调度问题 问题&#xff1a;由n项任务&#xff0c;每项任务的加工时间已知&#xff0c;从零时刻开始陆续加入一台机器上去加工&#xff0c;每个任务完成的时间是从0时刻到任务加工截至的时间。 求总完成时间&#xff08;所有任务完成时间最短计划方案&#xf…

PostMan测试文件上传

后端代码 package com.example.backend.controller;import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.StrUtil; import com.example.backend.common.Result; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import org…

Python Web开发记录 Day9:Django part3 用户管理

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 1、数据库准备2、用户列表3、新建用户4、编辑用…

科研学习|论文解读——美国政治经济中的权力:网络分析(JASIST, 2019)

论文原题目 Power in the U.S. political economy: A network analysis 摘要 美国政治经济的许多特征产生于大型政治和经济机构之间的互动&#xff0c;然而我们对它们的互动性质和这些机构之间的权力分配知之甚少。在本文中&#xff0c;对总部设在美国的组织的网络进行了详细的…

学习shell脚本

文章目录 什么是shell脚本为什么要学习shell脚本第一个脚本编写与执行 简单的shell脚本练习简单案例脚本的执行方式差异(source、sh script、./script) 如何使用shell脚本的判断式利用test命令的测试功能利用判断符号[ ]shell脚本的默认变量($0、$1...) shell脚本的条件判断式利…

2.3 物理层设备

2.3 物理层设备 &#xff08;一&#xff09;中继器 产生原因 由于存在损耗&#xff0c;在线路上传输的信号功率会逐渐衰减&#xff0c;衰减到一定程度时将造成信号失真&#xff0c;因此会导致接收错误。 中继器的功能 对信号进行再生和还原&#xff0c;对衰减的信号进行放大…

VMware Worksation 问题

几个晚上在虚拟机装了好多东西&#xff0c;配置mysql&#xff0c;配置docker、Git工具等等&#xff0c;可能废寝忘食导致太困强制关了虚拟机&#xff0c;结果第二天晚上回来发现打不开&#xff0c;心态直接崩了。 问题&#xff1a; 疯狂百度告知要删除后缀为.lck的文件夹及文件…

网络爬虫丨基于scrapy+mysql爬取博客信息

文章目录 写在前面实验描述实验框架实验需求 实验内容1.安装依赖库2.创建Scrapy项目3.配置系统设置4.配置管道文件5.连接数据库6.分析要爬取的内容7.编写爬虫文件 运行结果写在后面 写在前面 本期内容&#xff1a;基于scrapymysql爬取博客信息并保存到数据库中 实验需求 ana…

如何快速搭建物联网工业云平台

随着物联网技术的快速发展&#xff0c;物联网工业云平台已经成为推动工业领域数字化转型的重要引擎。合沃作为专业的物联网云服务提供商&#xff0c;致力于为企业提供高效、可靠的物联网工业云平台解决方案。本文将深入探讨物联网工业云平台的功能、解决行业痛点的能力以及如何…

每日OJ题_简单多问题dp⑦_力扣123. 买卖股票的最佳时机 III

目录 力扣123. 买卖股票的最佳时机 III 状态机分析 解析代码 力扣123. 买卖股票的最佳时机 III 123. 买卖股票的最佳时机 III 难度 困难 给定一个数组&#xff0c;它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以…

D 咖智能饮品机入驻万达,引领时尚饮品新潮流!

近日&#xff0c;D 咖智能饮品机正式入驻万达广场&#xff0c;为广大消费者带来全新的时尚饮品体验。作为国内领先的智能饮品设备品牌&#xff0c;D 咖智能饮品机以其多样化的口味选择、便捷的操作方式和个性化的定制服务&#xff0c;受到了众多消费者的喜爱。 D 咖智能饮品机提…

基于Verilog的简易CPU设计

前言 本篇文章将简单讲解CPU之间各部分的功能及接线&#xff0c;并提供Verilog模拟CPU的各个组成部分。该CPU可以完成一些操作&#xff0c;如&#xff1a;加减法&#xff0c;与或&#xff0c;指令跳转等&#xff0c;最后提供testbench用于测试该CPU的工作情况是否符合预期。 C…