当前位置: 首页 > news >正文

分布式锁理解

介绍分布式锁,我觉得从项目的背景入手把

在伙伴匹配系统中,我创建了一个定时任务,做为缓存预热的手段

这个具体原因在Redis-CSDN博客

接下来切入正题:

想象每个服务器都有一个定时任务,都要对数据库或者缓存进行操作

这会带来什么问题?

1:首先最先想到的肯定是资源浪费

2:其次如果我这个定时任务是一个插入操作,那是不是会导致数据库或者缓存有很多的重复数据

再或者是一个修改操作,那肯定会造成结果不唯一的错误

那知道了问题,我们就要去想怎么解决?

解决办法

其实这个问题有点像操作系统中的临界区的问题

如果学过操作系统应该就很容易想到:

讲到了锁,那这个锁是一般的锁能锁得住嘛?

锁:

Java 实现锁:synchronized 关键字,这个在学习线程的时候学习过,很容易理解,

不过有个问题,这个synchronized是只对一个JVM有效

我们这里的项目场景可以用这个方法解决嘛?

显然不行,因为你一个synchronized只能锁住一个服务器,有多个服务器同时操作,你还是没有办法

接下来就引出

分布式锁

但是分布式锁这个东西需要考虑的点有很多:

分布式锁的注意事项:

  1. 用完锁要释放(腾地方)
  2. 锁一定要加过期时间 
  3. 如果方法执行时间过长,锁提前过期了?
  4. 连锁效应:释放掉别人的锁
  5. 这样还是会存在多个方法同时执行的情况

解决方案:续期(看门狗机制)

分布式锁概述:

处理多个并发操作的情况,确保在分布式系统中的不同节点(不同服务器)上对共享资源的访问是有序的和安全的

什么意思呢:

有一个房间(数据库),有三台服务器ABC,他们都有这个定时任务,想要进去操作数据库

我们规定,ABC三个服务器需要抢夺一把锁,抢到的才能进入,进去之后并且还需要锁上门

这就和Java多线程很像。

分布式锁的实现:

说了这么多,我们应该怎么保证同一时间只有一个服务器能抢到锁呢?

核心思想:

先来的人先把数据改成自己的标识(服务器 ip),后来的人发现标识已存在,就抢锁失败,继续等待。

等先来的人执行方法结束,把标识清空,其他的人继续抢锁


下面介绍Redis实现分布式锁(我只会这个,等以后会得多了再来补充把)

分布式锁的实现:Redis

主要是基于命令:SETNX key value

塞滕克斯 |文档 --- SETNX | Docs (redis.io)

redis> SETNX mykey "Hello"
(integer) 1
redis> SETNX mykey "World"
(integer) 0
redis> GET mykey
"Hello"

用了setnx将mykey(key)设置为"Hello"(value)之后,不允许再更改了

更改会返回0。

当然如果我们直接用setnx命令去操作就很麻烦,就介绍下面这一个方法:

Redisson 实现分布式锁:

Redisson 是一个 java 操作 Redis 的客户端,提供了大量的分布式数据集来简化对 Redis 的操作和使用,可以让开发者像使用本地集合一样使用 Redis,完全感知不到 Redis 的存在。

还是贴一个官方文档:

https://github.com/redisson/redisson#quick-start

1:引入依赖:
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.32.0</version>
</dependency>  
2:配置:
package com.usercenter.usercenterproject.config;/*
Redission的配置*/import lombok.Data;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@ConfigurationProperties
@Data
public class RedissionConfiguration {private String host;private String port;@Beanpublic RedissonClient redissonClient(){// 1. Create config objectConfig config = new Config();String address = String.format("redis://127.0.0.1:6379");config.useSingleServer().setAddress(address).setDatabase(3);// 2. Create Redisson instance// Sync and Async APIRedissonClient redisson = Redisson.create(config);return redisson;}}

这段直接复制官方文档,改一下地址就行。

还需要配置成单机模式config.useSingleServer()

3:Redisson得使用:       
a.获取锁对象getLock:
final RLock lock = redissonClient.getLock("shayu:user:recommend:lock");
b.尝试获取锁的操作tryLock:
lock.tryLock(0,-1,TimeUnit.MILLISECONDS)

tryLock 方法会立即返回 false,表示获取锁失败;

而当锁可用时,则尝试获取锁并返回 true,表示成功获取锁。

tryLock这个方法有三个参数:

  1. waitTime:等待时间,即尝试获取锁的最大等待时间。这个参数表示在尝试获取锁时最多愿意等待的时间长度,单位可以是毫秒或者其他时间单位。如果在等待时间内未能成功获取锁,则 tryLock 方法会返回 false。(这个得意思就是其它没有拿到这个锁得服务器,他们不能一直等待,等过了这个waitTime之后就会放弃抢锁)这里的waitTime可以设置为0,因为我们这个定时任务,只要有一个服务器获取了,其它服务器就不能再操作了

  2. leaseTime:租约时间,表示获取锁成功后的租约时长。这个参数指定了成功获取锁后的持有时间长度,即锁的有效期,单位也可以是毫秒或其他时间单位。当锁的持有时间达到租约时长后,系统会自动释放锁。(表示这个获得锁的服务器的最长拥有时间,过了这个拥有时间,这个服务器就必须释放锁)这个leaseTime这里设置为-1,这是因为后面的看门狗机制

  3. unit:时间单位,用于指定 waitTime 和 leaseTime 的时间单位,可以是 TimeUnit 中预定义的时间单位,例如 TimeUnit.MILLISECONDS 表示毫秒。这个参数用于确保 waitTime 和 leaseTime 的时间粒度符合需求。

c.释放锁unlock():

获取锁之后一定要释放

还有一个点,在释放锁之前要确认一下是否是自己的锁:lock.isHeldByCurrentThread()

        finally {if(lock.isHeldByCurrentThread()){System.out.println("unlock"+Thread.currentThread().getId());lock.unlock();}}

可以将释放锁这段代码放在finally,因为创建锁需要捕获异常,如果不在finally中释放,就可以会发生这个锁一直存在这种现象。

Redisson的看门狗机制:

我们设想一个场景,假设一台服务器获取了锁之后,要往数据库中插入数据,全部插入完的时间是30ms,不过锁的过期时间是20ms,那这样就会发生问题:

我操作还没做完,这个锁就过期了,这怎么行。

所以:Redisson的看门狗机制就可以解决这个问题:

这个机制可以自动延长锁的过期时间(只要你不释放锁,就会一直延长)

如何启动这个看门狗机制呢?

只要在tryLock的realseTime中传入-1,就可以启动Redisson的看门狗机制。

相关文章:

分布式锁理解

介绍分布式锁&#xff0c;我觉得从项目的背景入手把 在伙伴匹配系统中&#xff0c;我创建了一个定时任务&#xff0c;做为缓存预热的手段 这个具体原因在Redis-CSDN博客 接下来切入正题&#xff1a; 想象每个服务器都有一个定时任务&#xff0c;都要对数据库或者缓存进行操…...

Android Gradle 开发与应用 (十): Gradle 脚本最佳实践

目录 1. 使用Gradle Kotlin DSL 1.1 什么是Gradle Kotlin DSL 1.2 迁移到Kotlin DSL 1.3 优势分析 2. 优化依赖管理 2.1 使用依赖版本管理文件 2.2 使用依赖分组 3. 合理使用Gradle插件 3.1 官方插件和自定义插件 3.2 插件管理的最佳实践 4. 任务配置优化 4.1 使用…...

c#获取本机的MAC地址(附源码)

在前一次的项目中&#xff0c;突然用到了这个获取本机的MAC地址&#xff0c;然后就研究了一下&#xff0c;记录下来&#xff0c;防止以后再用到&#xff0c; 使用winfrom做的&#xff0c;界面一个button&#xff0c;一个textBox,点了button以后给textBox赋值显示mac地址 附上源…...

sqlmap使用之-post注入、head注入(ua、cookie、referer)

1、post注入 1.1、方法一&#xff0c;通过保存数据包文件进行注入 bp抓包获取post数据 将数据保存到post.txt文件 加上-r指定数据文件 1.2、方法二、通过URL注入 D:\Python3.8.6\SQLmap>python sqlmap.py -u "http://localhost/login.php" --data "userna…...

XSS: 原理 反射型实例[入门]

原理 服务器未对用户输入进行严格校验&#xff0c;使攻击者将恶意的js代码&#xff0c;拼接到前端代码中&#xff0c;从而实现恶意利用 XSS攻击危害 窃取用户Cookie和其他敏感信息&#xff0c;进行会话劫持或身份冒充后台增删改文章进行XSS钓鱼攻击利用XSS漏洞进行网页代码的…...

Idea新增Module报错:sdk ‘1.8‘ type ‘JavaSDK‘ is not registered in ProjectJdkTable

文章目录 一&#xff0c;创建Module报错二&#xff0c;原因分析三&#xff0c;解决方案1&#xff0c;点击上图的加号&#xff0c;把JDK8添加进来即可2&#xff0c;点击左侧[Project]&#xff0c;直接设置SDK为JDK8 四&#xff0c;配置检查与验证 一&#xff0c;创建Module报错 …...

基于RHCE基础搭建简单服务

目录 项目标题与需求一 配置IP地址server机node02机 二 配置web服务三 搭建dns服务器四 开启防火墙server firewalld 五 配置nfs服务器node02 nfsserver autofs 六 开启SELinux七 验证是否能访问www.rhce.com 项目标题与需求 项目标题&#xff1a; 项目需求&#xff1a; 现有…...

威纶通触摸屏软件离线仿真时出现报错8000端口占用或服务器断线

现象 威纶通触摸屏软件离线仿真时出现报错 显示8000端口被占用 或者是设备服务器断线的状态 处理方法 系统参数——HMI属性 端口号更改一下即可 或者关闭占用8000端口的应用 分享创作不易&#xff0c;请多多支持&#xff0c;点赞、收藏、关注&#xff01; Ending~...

CAS详解

文章目录 CAS使用示例Unsafe类实现原理CAS问题 CAS CAS全称为Compare and Swap被译为比较并交换&#xff0c;是一种无锁算法。用于实现并发编程中的原子操作。CAS操作检查某个变量是否与预期的值相同&#xff0c;如果相同则将其更新为新值。CAS操作是原子的&#xff0c;这意味…...

【笔记】虚拟机中的主从数据库连接实体数据库成功后的从数据库不同步问题解决方法2

错误&#xff1a; Last_Errno: 1008 Last_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction ANONYMOUS at source log mysql-bin.000014, end_log_pos 200275. See error lo…...

【每日一练】python类和对象现实举例详细讲解

""" 本节课程目的&#xff1a; 1.掌握类描述现实世界实物思想 2.掌握类和对象的关系 3.理解什么事面向对象 """ #比如设计一个闹钟&#xff0c;在这里就新建一个类 class Clock:idNone #闹钟的序列号&#xff0c;也就是类的属性priceNone #闹…...

【学习css1】flex布局-页面footer部分保持在网页底部

中间内容高度不够屏幕高度撑不开的页面时候&#xff0c;页面footer部分都能保持在网页页脚&#xff08;最底部&#xff09;的方法 1、首先上图看显示效果 2、奉上源码 2.1、html部分 <body><header>头部</header><main>主区域</main><foot…...

Java中创建线程的几种方式

底层都是基于实现Runnable接口 1.继承thread类&#xff0c;new一个thread对象&#xff0c;实现run方法&#xff0c;无返回值 public class MyThread extends Thread {Overridepublic void run() {System.out.println("Thread created by extending Thread class is runn…...

[A-04] ARMv8/ARMv9-Cache的相关策略

ver0.2 前言 前面我们已经通过三篇文章反反复复的讲Cache的概念、结构、架构&#xff0c;相信大家对Cache已经大概有了初步的了解。这里简单归纳一下: (1) Cache从硬件视角看&#xff0c;是连接PE-Core和主存的一种存储介质&#xff0c;存储的数据是主存中数据的副本&#xf…...

【笔试常见编程题06】最近公共祖先、求最大连续bit数、二进制插入、查找组成一个偶数最接近的两个素数

1. 最近公共祖先 将一棵无穷大满二叉树的结点按根结点一层一层地从左往右编号&#xff0c;根结点编号为1。现给定a&#xff0c;b为两个结点。设计一个算法&#xff0c;返回a、b最近的公共祖先的编号。注意其祖先也可能是结点本身。 测试样例&#xff1a; 2&#xff0c;3 返回&a…...

【工具分享】Gophish——网络钓鱼框架

文章目录 Gophish安装方式功能简介 Gophish Gophish 是一个开源的网络钓鱼框架&#xff0c;它被设计用于模拟真实世界的钓鱼攻击&#xff0c;以帮助企业和渗透测试人员测试和评估他们的网络钓鱼风险。Gophish 旨在使行业级的网络钓鱼培训对每个人都是可获取的&#xff0c;它易…...

“职业三大底层逻辑“是啥呢?

大家好&#xff0c;我是有用就扩散。 掌握职业发展的三大底层逻辑以宏观视角看待自己的职业发展道路具备长远规划自己职业路劲的能力通过成就事件呈现自己的工作成绩 一、痛点陈述 不喜欢眼前的工作&#xff1f;眼前的工作琐碎没前途&#xff1f;找不到能力提升的方向时候会…...

飞睿智能无线高速uwb安全数据传输模块,低功耗、抗干扰超宽带uwb芯片传输速度技术新突破

在信息化的时代&#xff0c;数据传输的速度和安全性无疑是每个企业和个人都极为关注的话题。随着科技的飞速发展&#xff0c;超宽带&#xff08;Ultra-Wideband&#xff0c;简称UWB&#xff09;技术凭借其性能和广泛的应用前景&#xff0c;逐渐成为了数据传输领域的新星。今天&…...

手把手教你从微信中取出聊天表情图片,以动态表情保存为gif为例

以下方法静态图片同样适用 收到动画表情像保存为gif 这时候我们就要借助微信官方的文件小助手网页版。 登录之后把要保存的表情转发给微信传输助手 这个时候就会出现将图像另存为 如果需要保存动图就修改后缀为.gif...

【深度学习】图形模型基础(5):线性回归模型第三部分:线性回归模型拟合

1.引言 本博文专辑的焦点主要集中在回归模型的实用案例和工具上&#xff0c;从简单的单变量线性回归入手&#xff0c;逐步过渡到包含多个预测变量、非线性模型&#xff0c;以及在预测和因果推断中的应用。本文我们将介绍回归模型推断的一些数学结构&#xff0c;并提供一些代数…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

BLEU评分:机器翻译质量评估的黄金标准

BLEU评分&#xff1a;机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域&#xff0c;衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标&#xff0c;自2002年由IBM的Kishore Papineni等人提出以来&#xff0c;…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟

2025年4月29日&#xff0c;在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上&#xff0c;可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞&#xff0c;强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...