商城項目【尚品匯】07分布式鎖-2 Redisson篇

1 Redisson功能介紹

基于自定義setnx實現的分布式鎖存在下面的問題:

重入問題:重入問題是指 獲得鎖的線程可以再次進入到相同的鎖的代碼塊中,可重入鎖的意義在于防止死鎖,比如HashTable這樣的代碼中,他的方法都是使用synchronized修飾的,假如他在一個方法內,調用另一個方法,那么此時如果是不可重入的,不就死鎖了嗎?所以可重入鎖他的主要意義是防止死鎖,我們的synchronized和Lock鎖都是可重入的。

不可重試:是指目前的分布式只能嘗試一次,我們認為合理的情況是:當線程在獲得鎖失敗后,他應該能再次嘗試獲得鎖。

**超時釋放:**我們在加鎖時增加了過期時間,這樣的我們可以防止死鎖,但是如果卡頓的時間超長,雖然我們采用了lua表達式防止刪鎖的時候,誤刪別人的鎖,但是畢竟沒有鎖住,有安全隱患

主從一致性: 如果Redis提供了主從集群,當我們向集群寫數據時,主機需要異步的將數據同步給從機,而萬一在同步過去之前,主機宕機了,就會出現死鎖問題。
在這里插入圖片描述
那么什么是Redisson呢

Redisson是一個在Redis的基礎上實現的Java駐內存數據網格(In-Memory Data Grid)。它不僅提供了一系列的分布式的Java常用對象,還提供了許多分布式服務,其中就包含了各種分布式鎖的實現。

Redission提供了分布式鎖的多種多樣的功能
在這里插入圖片描述

2 Redisson在Springboot中快速入門(代碼)

2.1 導入依賴

<!-- redisson -->
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.15.3</version>
</dependency>

2.2 Redisson配置

package com.atguigu.gmall.common.config;import lombok.Data;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;/*** redisson配置信息*/
@Data
@Configuration
@ConfigurationProperties("spring.redis")
public class RedissonConfig {private String host;private String addresses;private String password;private String port;private int timeout = 3000;private int connectionPoolSize = 64;private int connectionMinimumIdleSize=10;private int pingConnectionInterval = 60000;private static String ADDRESS_PREFIX = "redis://";/*** 自動裝配**/@BeanRedissonClient redissonSingle() {Config config = new Config();if(StringUtils.isEmpty(host)){throw new RuntimeException("host is  empty");}SingleServerConfig serverConfig = config.useSingleServer()//redis://127.0.0.1:7181.setAddress(ADDRESS_PREFIX + this.host + ":" + port).setTimeout(this.timeout).setPingConnectionInterval(pingConnectionInterval).setConnectionPoolSize(this.connectionPoolSize).setConnectionMinimumIdleSize(this.connectionMinimumIdleSize);if(!StringUtils.isEmpty(this.password)) {serverConfig.setPassword(this.password);}// RedissonClient redisson = Redisson.create(config);return Redisson.create(config);}
}

2.3 將自定義鎖setnx換成Redisson實現(可重入鎖)

實現類詳細看這個章節:https://blog.csdn.net/yu_fu_a_bu/article/details/139408497

3 可重入鎖原理

3.1 自定義分布式鎖setnx為什么不可以重入

數據結構:key-value的形式。String類型
在這里插入圖片描述

public class DistributedLockExample {private static Jedis jedis = new Jedis("127.0.0.1", 6379);public void acquireLock(String lockKey) {Boolean locked = jedis.setnx(lockKey, "true");if (locked) {System.out.println("Lock acquired successfully.");} else {System.out.println("Lock already acquired by another process.");}}public static void main(String[] args) {DistributedLockExample example = new DistributedLockExample();example.acquireLock("myLock");example.acquireLock("myLock"); // 嘗試重入}
}

在上面的示例中,acquireLock方法通過setnx嘗試獲取鎖。第一次調用acquireLock時成功獲取鎖,因為myLock這個key在Redis中不存在。第二次調用acquireLock嘗試重入時,會返回鎖已被占用的提示,因為Redis的setnx指令無法識別重入情況,每次獲取鎖都需要先檢查是否已被占用。

3.2 redisson為什么可以實現可重入

數據類型:key-value(field-value) Hash類型在這里插入圖片描述

不僅存入線程標識(保證不刪除別人的鎖),而且存入可重入的次數(保證可重入)。

在這里插入圖片描述

3.2.1 獲取鎖的lua腳本

lua腳本可以保證原子性

local key = KEYS[1];--鎖的key
local threadId = ARGV[1]; --線程的唯一標識
local releaseTime = ARGV[2];--鎖的自動釋放時間
--判斷鎖是否存在
if(redis.call('exists',key) == 0) then --不存在,獲取鎖redis.call('hset', key,threadId,'1');--設置有效期redis.call('expire',key,releaseTime);return 1;--返回結果
end;
--如果鎖已經存在,判斷threadId是否是自己的
if(redis.call('hexists',key,threadId) == 1) then--存在,獲取鎖,重入次數加一redis.call('hincrby',key,threadId,'1');-- 設置有效期redis.call('expire',key,releaseTime);return 1;--返回結果
end;
return 0;--獲取鎖失敗

3.2.2 釋放鎖的lua腳本

local key = KEYS[1];--鎖的key
local threadId = ARGV[1]; --鎖的唯一標識
local releaseTime = ARGV[2];--鎖的自動釋放時間
-- 判斷鎖是還是被自己持有
if(redis.call('HEXISTS',key,threadId) == 0) then return nil;--如果已經不是自己,則直接返回
end;
-- 是自己的鎖,則可重入的次數進行-1
local count = redis.call('HINCRVY',key,threadId,-1);
-- 判斷可重入的次數是否為0
if(count > 0){-- 大于0說明不能釋放鎖,重置過期時間然后返回redis.call('EXPIRE',key,releaseTime);return nil;
else --等于0說明可以釋放鎖,直接刪除redis.call('DEL',key);return nil;
end;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/22187.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/22187.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/22187.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LightGBM 進行回歸建模的流程

LightGBM 進行回歸建模的流程 文章最前&#xff1a; 我是Octopus&#xff0c;這個名字來源于我的中文名–章魚&#xff1b;我熱愛編程、熱愛算法、熱愛開源。所有源碼在我的個人github &#xff1b;這博客是記錄我學習的點點滴滴&#xff0c;如果您對 Python、Java、AI、算法有…

將HTML頁面中的table表格元素轉換為矩形,計算出每個單元格的寬高以及左上角坐標點,輸出為json數據

export function huoQuTableElement() {const tableData []; // 存儲表格數據的數組let res [];// 獲取到包含表格的foreignObject元素const foreignObject document.getElementById(mydctable);if (!foreignObject){return ;}// 獲取到表格元素let oldTable foreignObject…

Nativefier : 將網址打包成exe桌面程序

1、需求場景 在日常開發中&#xff0c;需要針對一些網頁在一體機上使用&#xff0c;同時在瀏覽器上也可以使用&#xff0c;這里推薦大家用nativefier&#xff0c;對網址進行打包。以下是nativefier安裝命令&#xff1a; npm install nativefier -g 2、使用方法 --arch 系統 …

《混凝土壩監測儀器系列型譜》修訂中監測儀器分類方案解讀

隨著科技的不斷進步和監測需求的日益增加&#xff0c;對監測儀器分類方案進行修訂已成為必然的趨勢。本文旨在探討《混凝土壩監測儀器系列型譜》中對現有儀器分類方式的修訂&#xff0c;以及監測儀器選用的相關內容。希望對大家中有所幫助&#xff1a; 一、取消過時條目&#x…

服務器是一種高性能計算機

服務器是一種高性能計算機&#xff0c;專門設計用于在網絡中提供各種服務。它們通常具備比普通計算機更快的CPU運算能力、更可靠的運行性能、更大的I/O外部數據吞吐能力以及更好的擴展性。

java中方法引用

目錄 方法引用&#xff1a; 引用靜態方法 引用成員方法 引用構造方法 使用類名引用成員方法 引用數組的構造方法 練習 方法引用&#xff1a; 把已經有的方法拿過來用&#xff0c;當做函數式接口中抽象方法的方法體 在Java中&#xff0c;方法引用是一種簡化Lambda表達式的…

詳解Spring支持的幾種注入方式

在 Spring 框架中&#xff0c;Bean 的注入方式主要有以下幾種&#xff0c;其中一些是自動注入的。以下是詳細說明&#xff1a; 1. 構造函數注入 (Constructor Injection) 自動注入&#xff1a;使用 Autowired 注解時&#xff0c;Spring 容器會自動調用帶有 Autowired 注解的構…

教務管理系統-學員辦理體系介紹

隨著時代的快速開展&#xff0c;教育方面也沒落下&#xff0c;不僅是線下線上都呈現許多訓練校園&#xff0c;辦理軟件也順勢而為的呈現廣闊訓練校園面前&#xff0c;許多的校園和訓練組織也都在運用教務管理系統了。運用教務管理系統里邊的學員辦理體系可以讓相應的辦理人員更…

Redis的一致性

一、產生的原因 使用緩存&#xff0c;在進行寫操作的時候就會出現不一致的問題。 一致性分為三類&#xff1a;強一致性&#xff0c;弱一致性&#xff0c;最終一致性 二、方案 2.1 延時雙刪 在更新數據庫的操作前后分別進行一次刪除緩存的操作&#xff0c;并在更新數據庫之后…

《HelloGitHub》第 98 期

興趣是最好的老師&#xff0c;HelloGitHub 讓你對編程感興趣&#xff01; 簡介 HelloGitHub 分享 GitHub 上有趣、入門級的開源項目。 github.com/521xueweihan/HelloGitHub 這里有實戰項目、入門教程、黑科技、開源書籍、大廠開源項目等&#xff0c;涵蓋多種編程語言 Python、…

Docker大學生看了都會系列(三、常用幫助、鏡像、容器命令)

系列文章目錄 第一章 Docker介紹 第二章 2.1 Mac通過Homebrew安裝Docker 第二章 2.2 CentOS安裝Docker 第三章 Docker常用命令 文章目錄 前言環境常用命令幫助命令鏡像命令容器命令 總結 前言 前面2章學完了基礎概念&#xff0c;實操安裝使用。接下來了解一些日常中常用的命令…

Java - 隨機存取文件類

在Java中&#xff0c;隨機存取文件&#xff08;Random Access File&#xff09;通常使用java.io.RandomAccessFile類來實現。這個類允許你讀取和寫入文件的任意位置&#xff0c;而不是像FileReader和FileWriter那樣只能從頭開始或追加到文件末尾。 RandomAccessFile類提供了用…

容器化部署fastdfs文件存儲

目錄 一、軟件信息 二、構建fastdfs鏡像 三、docker 啟動fdfs服務 四、k8s部署fdfs服務 1、fdfs部署文件 五、外部服務訪問 一、軟件信息 fastdfs版本&#xff1a;fastdfs:V5.11 libfastcommon版本: V1.0.36 fastdfs-nginx-module版本&#xff1a;V1.20 nginx版本&…

速盾:cdn技術詳解

CDN&#xff08;Content Delivery Network&#xff0c;內容分發網絡&#xff09;是一種基于分布式架構的網絡技術&#xff0c;通過將內容緩存到離用戶較近的服務器上&#xff0c;從而提升網站的訪問速度和可靠性。本文將詳細介紹CDN技術的原理和工作流程。 CDN技術的原理是將網…

h5相機功能

h5相機功能 利用vant input file <template><div class"mb10"><divv-for"(item, index) in info.imgList":key"index"class"imgItem f32 mr20"click"preview(item, index)"><img :src"doFileUrl…

<sa8650>QCX Usecase 使用詳解—如何在管道中添加多個 IPE 實例

<sa8650>QCX Usecase 使用詳解—如何在管道中添加多個 IPE 實例 一、前言二、UsecaseSRV添加新格式三、更新usecase.xml四、定義 IPE 的新實例五、添加新鏈接六、QCarcam測試XML一、前言 本節說明在使用Usecase/Pipeline XML 中添加多個 IPE 實例所需的更改。以下示例解釋了…

使用Spring Boot和MybatisPlus的Java CRM客戶關系管理系統源碼

項目名稱&#xff1a;CRM客戶關系管理系統 功能模塊及描述&#xff1a; 一、待辦事項 今日需聯系客戶&#xff1a;顯示當日需跟進的客戶列表&#xff0c;支持查詢和篩選。 分配給我的線索&#xff1a;管理分配給用戶的線索&#xff0c;包括線索列表和查詢功能。 分配給我的客…

導彈研究中常用坐標系及坐標系之間的變換

在導彈飛行控制過程中&#xff0c;需要時刻掌握導彈的飛行狀態 &#xff08;速度、位置、姿態角等&#xff09;&#xff0c;這就有賴于描述導彈飛行狀態的坐標系。除了大地坐標系和地心大地直角坐標系外&#xff0c;導彈常用的坐標系還有很多&#xff0c;合理而恰當地選擇參考系…

golang調用外部程序包os/exec中的 Command和CommandContext 函數創建的Cmd對象的區別

在go語言中&#xff0c;我們可以通過os/exec包中的Command和CommandContext 函數創建對應的外部程序執行Cmd對象&#xff0c; 這2個函數創建的cmd命令執行對象是有區別的&#xff0c;CommandContext創建的對象可以攜帶上下文&#xff0c;這個主要用于我們通過cancel函數給對應的…

37【透視】兩點透視

1 兩點透視比較合適表現物體的結構 用兩點透視繪制比較小的、箱子之類的物體 2 一點透視和兩點透視的共存關系