Redisson-分布式鎖單Redis節點模式

Redisson-分布式鎖單Redis節點模式

為什么要用分布式鎖?

使用分布式鎖的主要目的是為了解決多線程或多進程并發訪問共享資源時可能出現的競爭條件和數據一致性問題。舉一些實際場?:

  1. 數據庫并發控制:在分布式系統中,多個節點同時操作數據庫時,可能會導致數據不一致或沖突。通過使用分布式鎖,可以確保同一時間只有一個節點能夠對特定數據進行修改,從而避免出現臟讀、幻讀等問題。
  2. 資源限制和瓶頸控制:某些資源(如文件、接口調用次數等)需要限制同時訪問的數量,在高并發環境下通過使用分布式鎖可以有效地控制資源的訪問數量。
  3. 防止死鎖:在復雜系統中,由于各種原因(如網絡故障、程序錯誤等),可能導致死鎖情況。通過使用帶有超時機制的分布式鎖,可以防止因為單個節點故障而導致整個系統陷入死鎖狀態。

使用分布式鎖能夠保證共享資源被安全地訪問和修改,并且能夠提供良好的并發性能和可靠性。

目前的市場使用的分布式鎖有哪些?(個人了解不代表所有)

  1. 基于數據庫的分布式鎖
    優點:簡單易實現,使用現有的數據庫即可,不需要額外的基礎設施。
    缺點:性能相對較低,數據庫的I/O操作開銷大,還需要處理數據庫的死鎖問題。

  2. 基于Redis的分布式鎖
    優點:高性能,Redis是內存數據庫,讀寫速度快,Redis支持多種數據結構,靈活性高。
    缺點:需要確保Redis集群的高可用性和一致性,否則可能導致鎖的失效。

  3. 基于Redisson的分布式鎖
    優點: 內置多種鎖的實現,適用于不同場景,提高了鎖的可靠性。
    缺點:封裝了很多功能,引入了一些額外的開銷,相對直接使用Redis的命令,增加了項目依賴。

  4. 基于Zookeeper的分布式鎖
    優點:實現分布式鎖的過程中能夠自動處理網絡分區和節點故障,支持臨時節點,可以自動釋放鎖。
    缺點:實現較為復雜!!!性能相對Redis較低,因為Zookeeper需要維護強一致性。

使用Redisson實現分布式鎖

我用的是Spring Boot 的框架,沒有什么心思寫文章就直接寫代碼吧~

demo包類結構
在這里插入圖片描述
pom.xml

<dependencies><!--  redis緩存  --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- Redisson分布式鎖   --><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.12.0</version></dependency></dependencies>

yml配置

server:port: 8081servlet:context-path: /api
spring:redis:host: 服務器ipport: 6379
#    password: 123456timeout: 60000database: 5

配置類

package com.springboot.redisson.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;@Data
@Configuration
@ConfigurationProperties("spring.redis")
public class RedissonConfig {private String host;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();//  判斷redis 的host是否為空if(StringUtils.isEmpty(host)){throw new RuntimeException("host is  empty");}//  配置host,port等參數SingleServerConfig serverConfig = config.useSingleServer()// 節點地址.setAddress(ADDRESS_PREFIX + this.host + ":" + port)// 命令等待超時,單位:毫秒.setTimeout(this.timeout).setPingConnectionInterval(pingConnectionInterval)// 連接池大小.setConnectionPoolSize(this.connectionPoolSize)// 最小空閑連接數.setConnectionMinimumIdleSize(this.connectionMinimumIdleSize);//  判斷進入redis 是否密碼if(!StringUtils.isEmpty(this.password)) {serverConfig.setPassword(this.password);}return Redisson.create(config);}
}

controller

package com.springboot.redisson.controller;import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RCountDownLatch;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.UUID;
import java.util.concurrent.TimeUnit;@Slf4j
@RestController
@RequestMapping("redisson")
public class RedissonController {@ResourceRedissonClient redissonSingle;@ResourceRedisTemplate<String,Object> redisTemplate;@GetMapping("/")private String TestString(){return "Hello redisson!";}/*** RLock lock = redissonSingle.getLock("my-redisson-lock");* lock.lock();* 使用的是可重入鎖*  可重入鎖: 可重入鎖是一個分布式鎖,它可以用于多個線程訪問同一把鎖的等待保證數據的唯一性*      例如: 當有一個線程在訪問一個可重入鎖的時候,就會自動加鎖,其它線程再次訪問同一把鎖有時候只能等待,*              當線程釋放鎖的時候,其它線程才可以訪問,每次只能有一個線程進行訪問,* @return*/@GetMapping("no1")public String TestRedisson01(){RLock lock = redissonSingle.getLock("my-redisson-lock");lock.lock();try {log.info("NO1加鎖成功,正在處理業務邏輯》》》》》");System.out.println("好長的業務");Thread.sleep(50000);} catch (InterruptedException e) {throw new RuntimeException(e);}finally {lock.unlock();log.info("NO1解鎖成功");}return "NO1線程已經走完成!";}@GetMapping("no2")public String TestRedisson02(){RLock lock = redissonSingle.getLock("my-redisson-lock");lock.lock();try {log.info("NO2加鎖成功,正在處理業務邏輯》》》》》");System.out.println("好長的業務");Thread.sleep(50000);} catch (InterruptedException e) {throw new RuntimeException(e);}finally {lock.unlock();log.info("NO2解鎖成功");}return "NO2線程已經走完成!";}/*** 讀寫鎖*   RReadWriteLock readWriteLock = redissonSingle.getReadWriteLock("my-lock");*         RLock rLock = readWriteLock.readLock();*         rLock.lock();*         rLock.unlock();*   讀寫鎖: 讀寫鎖是一個分布式鎖,它允許多個線程同時讀,但是只允許一個線程寫,寫操作的時候,讀操作會被阻塞,*/@GetMapping("read")public String TestReadLock(){RReadWriteLock readWriteLock = redissonSingle.getReadWriteLock("my-lock");RLock rLock = readWriteLock.readLock();rLock.lock();String s = "";try {log.info("讀寫鎖操作中,正在處理業務邏輯》》》》》");s = UUID.randomUUID().toString();redisTemplate.opsForValue().set("redisson:readWriteLock",s,200, TimeUnit.SECONDS);Thread.sleep(5000);}catch (Exception e){e.printStackTrace();}finally {rLock.unlock();}return s;}@GetMapping("writel")public String TestWriteLock(){RReadWriteLock readWriteLock = redissonSingle.getReadWriteLock("my-lock");RLock rLock = readWriteLock.writeLock();rLock.lock();String s = "";try {log.info("讀鎖操作中,正在處理業務邏輯》》》》》");String key = (String) redisTemplate.opsForValue().get("redisson:readWriteLock");if (!StringUtils.isEmpty(key)){s = key;}}catch (Exception e){e.printStackTrace();}finally {rLock.unlock();}return s;}/*** 閉鎖*  RCountDownLatch door = redissonSingle.getCountDownLatch("door");*             door.trySetCount(5);*             door.await();**             door.countDown();*  閉鎖: 閉鎖是一個分布式閉鎖,它允許一個或多個線程等待,直到其他線程完成一系列操作,然后才繼續執行。*/@GetMapping("/lockDoor")public String lockDoor(){try {RCountDownLatch door = redissonSingle.getCountDownLatch("door");door.trySetCount(5);door.await();} catch (InterruptedException e) {throw new RuntimeException(e);}return "放假了。。。。。";}@GetMapping("/gogo/{id}")public String gogo(@PathVariable("id")String id){RCountDownLatch door = redissonSingle.getCountDownLatch("door");door.countDown();return id+"班的人都走了。。。。。";}@GetMapping("/modify")public String modifyData(){RLock lock = redissonSingle.getLock("my_modify_locl");if (!lock.tryLock()){return "修改失敗,當前信息正在被人修改";}try {System.out.println("運行一個超長代碼中");Thread.sleep(50000);return "修改成功";}catch (Exception e){e.printStackTrace();}finally {lock.unlock();}return "最后的代碼";}
}

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

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

相關文章

虛擬機上部署java微服務

在Windows服務器上安裝Ubuntu系統&#xff0c;先安裝虛擬機&#xff0c;然后再虛擬機上安裝Ubuntu系統 啟動虛擬機上的Ubuntu系統&#xff0c;然后安裝jdk。安裝好的Ubuntu系統是帶桌面版的&#xff0c;需要打開 “終端” 控制臺&#xff0c;通過命令行交互的方式部署程序&…

git 合并多個commit 使分支保持一次提交

1.控制臺輸入 git log 查看commit歷史 找到歷史提交sha 2.控制臺輸入 git rebase -i d0c5de8f7ca8e58fef347b36dd6b0f42f551cdb4 進入變基 3.輸入英文i進入VM輸入模式 4.保留第一行的pick 后面的pick改為s 5.esc退出輸入模式 6.輸入:wq保存退出 7.輸入英文i進入VM輸入模式…

從0開始實現一個博客系統 (SSM 實現)

相關技術 Spring Spring Boot Spring MVC MyBatis Html Css JS 實現功能 用戶注冊 - 密碼加鹽加密 (md5 加密)前后端用戶信息存儲 - 令牌技術用戶登錄 - (使用 攔截器 做登錄校驗)博客的增刪改查后端數據返回前端, 采用 SpringBoot 做統一功能處理和統一異常處理 數據…

軟考-程序員 知識點與部分真題梳理

軟考-程序員 知識點與部分真題梳理 參照《程序員教程》第五版劃分類別&#xff1b; 持續更新中… 計算機系統基礎知識 如何理解和處理浮點數的加減法運算 在計算機科學中&#xff0c;處理浮點數的表示和運算是基礎且關鍵的&#xff0c;尤其是在進行科學計算、圖形處理和數據分…

V2I(車與基礎設施)介紹

V2I&#xff08;車與基礎設施&#xff09;介紹 一、V2I技術概述 V2I&#xff08;Vehicle-to-Infrastructure&#xff09;技術&#xff0c;全稱汽車與基礎設施通訊&#xff0c;也被稱為信號燈系統。它通過無線通信技術&#xff0c;為車載智能交通運輸系統設立了專門的通信頻段…

【網絡】為什么udp協議報頭有長度字段,而tcp沒有

引言&#xff1a; 在網絡通信中&#xff0c;UDP&#xff08;用戶數據報協議&#xff09;和TCP&#xff08;傳輸控制協議&#xff09;是兩種常用的傳輸層協議。它們在設計和功能上有一些不同之處&#xff0c;其中之一就是報頭中的長度字段。本文將深入探討UDP和TCP協議中長度字…

SpringCloud Alibaba詳解:打造高可用的分布式系統

SpringCloud Alibaba是一個基于Spring Cloud的微服務開發框架&#xff0c;它集成了阿里巴巴的一系列中間件和工具&#xff0c;能夠快速構建高可用的分布式系統。在本文中&#xff0c;將詳細介紹如何使用SpringCloud Alibaba來打造高可用的分布式系統&#xff0c;并通過代碼案例…

第十一課,end關鍵字、簡單while循環嵌套、初識for循環

一&#xff0c;end關鍵字 end關鍵字用于在print輸出的內容后面聲明結束的字符&#xff0c;我們之前學過并且十分了解print是默認輸出內容之后跟著換行的&#xff0c;如果我們不希望換行而希望使用其它字符來代替換行&#xff0c;就可以用end關鍵字來實現 特殊的&#xff0c;en…

k8s筆記 | 高度調度

CronJob計劃任務 簡介&#xff1a;在k8s中周期性運行計劃任務&#xff0c;與linux中的crontab相同&#xff1b;注意點 CornJob執行的時間是controller-manager的時間&#xff0c;所以一定要確保controller-manager的時間是準確的&#xff0c;另外cornjob cron表達式 文章參…

xjoi題庫一級三段題解(c語言版)

浮點數 時間&#xff1a;0.2 空間&#xff1a;32M 題目描述&#xff1a; 小鸚鵡正在學習浮點數&#xff0c;你跟他說一個浮點數&#xff0c;他立刻就能學會。 輸入一個浮點數&#xff0c;輸出這個浮點數。 輸入格式&#xff1a; 輸入一個浮點數 輸出格式&#xff1a; 輸出一個…

2024.5.25AcWing刷題記錄-排序篇

一、786. 第k個數 - AcWing題庫 三路快速排序 import random def func(nums, start, end):if start > end:return idx random.randint(start, end)base nums[idx]i, j, m start, start, end 1while j < m:if nums[j] < base:nums[i], nums[j] nums[j], nums[i]…

Redis機制-Redis緩存穿透,擊穿,雪崩理解等問題的理解和學習

目錄 一 緩存穿透問題 二 緩存擊穿問題 三 緩存雪崩問題&#xff1a; 圖1 正常的Redis緩存流程 一 緩存穿透問題 我們都知道Redis是一個存儲鍵值對的非關系型數據庫&#xff0c;那么當用戶進行查詢的時候&#xff0c;勢必會從前端發起請求&#xff0c;從而數據從Redis緩存…

內網穿透--Frp-簡易型(速成)-上線

免責聲明:本文僅做技術交流與學習... 目錄 frp項目介紹: 一圖通解: ?編輯 1-下載frp 2-服務端(server)開啟frp口 3-kali客戶端(client)連接frp服務器 4-kali生成馬子 5-kali監聽 6-馬子執行-->成功上線 frp項目介紹: GitHub - fatedier/frp: A fast reverse proxy…

論文精讀-SwinIR Image Restoration Using Swin Transformer

論文精讀-SwinIR: Image Restoration Using Swin Transformer SwinIR:使用 Swin Transformer進行圖像恢復 參數量&#xff1a;SR 11.8M、JPEG壓縮偽影 11.5M、去噪 12.0M 優點&#xff1a;1、提出了新的網絡結構。它采用分塊設計。包括淺層特征提取&#xff1a;cnn提取&#…

Verilog實戰學習到RiscV - 1 : Yosys 綜合

Yosys 綜合 實例 一般 FPGA IDE 的第一步都是RTL 綜合&#xff08;Synthesis&#xff09;。之后就能看到數字電路圖了。然后可以做RTL 級的仿真模擬。 直接上代碼&#xff0c;這里我們看一個簡單的加法器來學習。 module adder(input [7:0] a,input [7:0] b, input …

Java延時隊列取消未支付的訂單 之 重啟服務任務丟失

一、定義延遲任務類 package com.activity.domain;import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit;/*** 延遲任務類*/ public class DelayedCancellation implements Delayed {private String order;private final long delayTime; // 延遲時間p…

鏈表類型的無界阻塞隊列-LinkedBlockingQueue

一:LinkedBlockingQueue介紹 1:LinkedBlockingQueue是一個基于鏈表實現的阻塞隊列,默認情況下,該阻塞隊列的大小為Integer.MAX_VALUE,由于這個數值特別大,所以 LinkedBlockingQueue 也被稱作無界隊列,代表它幾乎沒有界限,隊列可以隨著元素的添加而動態增長,但是如果沒…

智能體之斯坦福AI小鎮(Generative Agents: Interactive Simulacra of Human Behavior)

相關代碼地址見文末 論文地址&#xff1a;Generative Agents: Interactive Simulacra of Human Behavior | Proceedings of the 36th Annual ACM Symposium on User Interface Software and Technology 1.概述 論文提出了一種多個智能體進行協同&#xff0c;進而模擬可信的人…

Python燃氣輪機汽車鋼棒整流電路控制圖統計模型過程潛力分析

&#x1f3af;要點 &#x1f3af;活塞模擬器&#xff1a;&#x1f58a;控制圖過程能力分析&#xff1a;Cp 對過程提供在規格上限和下限內的輸出的潛力度量&#xff0c;Cpk中心過程能力指數&#xff0c;Cpl估計僅包含規格下限過程能力&#xff0c;Cpu估計僅包含規格上限過程能力…

Linux系統下Mysql忘記密碼怎么解決

一、對Mysql配置文件進行設置 1、找到/etc/mysql/my.cnf路徑下&#xff0c;用Vi命令編輯my.cnf配置文件&#xff0c;命令如下&#xff1a; # 以管理員身份登錄 sudo su # 輸入管理員密碼 # 登錄成功后&#xff0c;找到Mysql的配置文件-->Mysql配置文件默認在此 cd /etc/my…