Redisson(三)应用场景及demo

一、基本的存储与查询

分布式环境下,为了方便多个进程之间的数据共享,可以使用RedissonClient的分布式集合类型,如List、Set、SortedSet等。 

1、demo

  <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.8.RELEASE</version><relativePath/></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--<dependency>--><!--<groupId>org.redisson</groupId>--><!--<artifactId>redisson-spring-boot-starter</artifactId>--><!--<version>3.23.5</version>--><!--</dependency>--><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.15.0</version></dependency></dependencies>
server.port = 7777
server.servlet.context-path=/redission#1、单机模式
#Redis url should start with redis:// or rediss:// (for SSL connection)
#my.redisson.address = redis://127.0.0.1:6379
#my.redisson.password = wtyy#2、哨兵模式
my.redisson.sentinel.schema=
my.redisson.sentinel.address = redis://xxx.xx.xxx1:19601,redis://xxx.xx.xxx2:19601,redis://xxx.xx.xxx3:19601
my.redisson.sentinel.password = N5WAXX4z9qw
my.redisson.sentinel.master = master-test
my.redisson.sentinel.database = 10

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RedissionConfig {@Value("${my.redisson.sentinel.address}")private String address;@Value("${my.redisson.sentinel.password}")private String password;@Value("${my.redisson.sentinel.master}")private String master;@Value("${my.redisson.sentinel.database}")private Integer dataBase;@Value("${my.redisson.sentinel.schema}")private String schema;/*** 所有对Redisson的使用都是通过RedissonClient对象*/@Bean(destroyMethod = "shutdown")public RedissonClient redissonClient(){Config config = new Config();config.useSentinelServers().setScanInterval(2000) // cluster state scan interval in milliseconds.addSentinelAddress(address.split(",")).setCheckSentinelsList(false).setMasterName(master).setPassword(password).setDatabase(dataBase);RedissonClient redissonClient = Redisson.create(config);return redissonClient;}
}
@Autowiredprivate RedissonClient redissonClient;@RequestMapping("/setStr")public void setStr(String key,String value){redissonClient.getBucket(key).set(value);}@RequestMapping("/getStr")public String getStr(String key){return (String) redissonClient.getBucket(key).get();}

 测试:

访问localhost:7777/redission/setStr?key=userName&value=李四

查看redis存储情况

访问localhost:7777/redission/getStr?key=userName  输出:李四

二、分布式锁

1、背景

关于jedis锁的几个痛点:(1)锁先于业务过期(2)主从节点不一致;

Redisson都很好的解决了。

2、特点

高效的分布式锁设计应该包含以下几个要点:

(1)互斥:

在分布式高并发的条件下,我们最需要保证,同一时刻只能有一个线程获得锁,这是最基本的一点

(2)防止死锁:

在分布式高并发的条件下,比如有个线程获得锁的同时,还没有来得及去释放锁,就因为系统故障或者其它原因使它无法执行释放锁的命令,导致其它线程都无法获得锁,造成死锁。所以分布式非常有必要设置锁的有效时间,确保系统出现故障后,在一定时间内能够主动去释放锁,避免造成死锁的情况。

(3)性能:

对于访问量大的共享资源,需要考虑减少锁等待的时间,避免导致大量线程阻塞。所以在锁的设计时,需要考虑两点:

① 锁的颗粒度要尽量小。比如你要通过锁来减库存,那这个锁的名称你可以设置成是商品的ID,而不是任取名称。这样这个锁只对当前商品有效,锁的颗粒度小。

② 锁的范围尽量要小。比如只要锁2行代码就可以解决问题的,就不要去锁10行代码了。

(4)重入:

ReentrantLock是可重入锁,它的特点是:同一个线程可以重复拿到同一个资源的锁。重入锁非常有利于资源的高效利用。

3、原理

 Redisson并没有通过setNx命令来实现加锁,而是基于 Redis+ 看⻔狗机制,自己实现了一套分布式锁逻辑。

(1)加锁机制:

当一个线程想要获取锁时,它会先尝试通过`getLock()`方法获取锁。如果获取成功,它将执行Lua脚本(保证这段复杂业务逻辑执行的原子性)并保存数据到Redis数据库。如果获取失败,一直通过while循环尝试获取锁,直到获取成功后,执行lua脚本,保存数据到redis数据库

如果多个线程同时尝试获取同一个锁,Redisson会将这些请求放入队列中,然后按照FIFO(先进先出)的方式逐个处理它们。如果有一个线程已经获得了锁并且没有释放,那么其他线程将会等待,直到这个线程释放锁。

(2)Watch Dog自动延期机制:

如果一个线程获得了锁但没有立即使用,而是发生了故障或超出了锁的使用期限,Redisson的Watch Dog机制会在一定时间内自动释放锁。用户可以设置锁的有效时间,如果不设置,默认的时间是30秒。

之前使用jedis加锁,提到过业务逻辑耗时较长锁已经过期了这种情况,所以redission加入了看门狗机制。它的作用就是 线程1 业务还没有执行完,时间就过了,线程1 还想持有锁的话,就会启动一个watch dog后台线程,不断的延长锁key的生存时间。

注意 正常这个看门狗线程是不启动的,还有就是这个看门狗启动后对整体性能也会有一定影响,所以不建议开启看门狗。

(3)锁的互斥机制:

Redisson确保同一时刻只有一个线程拥有锁。当一个线程获取到锁后,它会将自己的信息保存在Redis中,以证明它是锁的所有者。当另一个线程试图获取相同的锁时,它会检查Redis中是否存在这条记录。如果存在,说明有其他线程已经拥有了锁,因此当前线程会被阻止继续执行。

(4)锁的释放机制:

当线程完成了所有的资源操作后,它应该及时释放锁。这可以通过发送一个`release()`命令来实现,Redisson会删除锁记录,从而允许其他线程重新获取锁。

综上所述,Redisson的分布式锁机制结合了Lua脚本的执行和Redis的操作,以及Watch Dog自动延期的功能,确保了锁的互斥性和释放的及时性。

(5)可重入:

它最大的优点就是相同线程不需要在等待锁,而是可以直接进行相应操作

4、使用方法
RLock lock = redisson.getLock("lock");
lock.lock();
try {// 处理业务逻辑
} finally {lock.unlock();
}

 升级写法:判断加锁是否成功

RLock lock = redissonClient.getLock(你的key);try {if (lock.tryLock()) {//你的业务逻辑} else {ResponseWrapper.error("冲突提示语");}} catch (Exception e) {log.error("异常");} finally {lock.unlock();}
5、demo
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service("productService")
public class ProductServiceImpl implements ProductService {
private static final Logger logger = LoggerFactory.getLogger(ProductServiceImpl.class);@Autowiredprivate RedissonClient redissonClient;int productTotal = 5;@Overridepublic void buy(String productId) {//模拟数据库查询if(productTotal > 0){logger.info(Thread.currentThread().getName()+"买到了一件");productTotal --;}logger.info("库存:"+productTotal);}@Overridepublic void lockBuy(String productId) {RLock lock = redissonClient.getLock(productId);lock.lock();try{//模拟数据库查询if(productTotal > 0){logger.info(Thread.currentThread().getName()+"买到了一件");productTotal --;}logger.info("库存:"+productTotal);}finally {lock.unlock();}}
}
 

 测试未加锁并发情况:

public class ProductTest implements Runnable{public static void main(String[] args) {ProductTest productTest = new ProductTest();for(int i=0;i<50;i++){Thread thread = new Thread(productTest);thread.start();}}@Overridepublic void run() {String url = "http://localhost:7777/redission/buy";String productId = "abcd";String param = "productId="+productId;HttpRequestUtil.sendGet(url, param);}
}

随机测试,20个并发量的情况下,出现负数,最大为 -4(如下图);并发量50时出现 -12。

而测试lockBuy接口,无论并发量为多少,都不会出现负数。打印50并发数的某一个结果:

2024-01-28 15:00:43.979  INFO 142656 --- [nio-7777-exec-6] com.demo.service.ProductServiceImpl      : http-nio-7777-exec-6买到了一件
2024-01-28 15:00:43.980  INFO 142656 --- [nio-7777-exec-6] com.demo.service.ProductServiceImpl      : 库存:4
2024-01-28 15:00:44.010  INFO 142656 --- [io-7777-exec-42] com.demo.service.ProductServiceImpl      : http-nio-7777-exec-42买到了一件
2024-01-28 15:00:44.013  INFO 142656 --- [io-7777-exec-42] com.demo.service.ProductServiceImpl      : 库存:3
2024-01-28 15:00:44.050  INFO 142656 --- [io-7777-exec-22] com.demo.service.ProductServiceImpl      : http-nio-7777-exec-22买到了一件
2024-01-28 15:00:44.050  INFO 142656 --- [io-7777-exec-22] com.demo.service.ProductServiceImpl      : 库存:2
2024-01-28 15:00:44.077  INFO 142656 --- [nio-7777-exec-5] com.demo.service.ProductServiceImpl      : http-nio-7777-exec-5买到了一件
2024-01-28 15:00:44.077  INFO 142656 --- [nio-7777-exec-5] com.demo.service.ProductServiceImpl      : 库存:1
2024-01-28 15:00:44.103  INFO 142656 --- [io-7777-exec-30] com.demo.service.ProductServiceImpl      : http-nio-7777-exec-30买到了一件
2024-01-28 15:00:44.103  INFO 142656 --- [io-7777-exec-30] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.121  INFO 142656 --- [io-7777-exec-14] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.129  INFO 142656 --- [io-7777-exec-46] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.138  INFO 142656 --- [io-7777-exec-11] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.146  INFO 142656 --- [nio-7777-exec-7] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.160  INFO 142656 --- [io-7777-exec-37] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.173  INFO 142656 --- [io-7777-exec-19] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.201  INFO 142656 --- [io-7777-exec-23] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.222  INFO 142656 --- [nio-7777-exec-8] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.244  INFO 142656 --- [io-7777-exec-18] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.277  INFO 142656 --- [io-7777-exec-15] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.314  INFO 142656 --- [io-7777-exec-41] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.339  INFO 142656 --- [io-7777-exec-24] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.365  INFO 142656 --- [io-7777-exec-10] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.392  INFO 142656 --- [io-7777-exec-21] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.411  INFO 142656 --- [io-7777-exec-45] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.431  INFO 142656 --- [io-7777-exec-48] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.455  INFO 142656 --- [io-7777-exec-13] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.473  INFO 142656 --- [io-7777-exec-32] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.502  INFO 142656 --- [nio-7777-exec-3] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.532  INFO 142656 --- [io-7777-exec-20] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.553  INFO 142656 --- [io-7777-exec-29] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.578  INFO 142656 --- [io-7777-exec-28] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.620  INFO 142656 --- [io-7777-exec-36] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.642  INFO 142656 --- [io-7777-exec-49] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.664  INFO 142656 --- [io-7777-exec-17] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.695  INFO 142656 --- [io-7777-exec-16] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.711  INFO 142656 --- [io-7777-exec-40] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.740  INFO 142656 --- [io-7777-exec-12] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.757  INFO 142656 --- [io-7777-exec-44] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.772  INFO 142656 --- [nio-7777-exec-2] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.789  INFO 142656 --- [io-7777-exec-26] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.814  INFO 142656 --- [io-7777-exec-27] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.830  INFO 142656 --- [io-7777-exec-50] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.845  INFO 142656 --- [io-7777-exec-43] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.863  INFO 142656 --- [io-7777-exec-35] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.887  INFO 142656 --- [io-7777-exec-47] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.912  INFO 142656 --- [io-7777-exec-34] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.937  INFO 142656 --- [nio-7777-exec-4] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.955  INFO 142656 --- [io-7777-exec-38] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:44.977  INFO 142656 --- [nio-7777-exec-9] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:45.008  INFO 142656 --- [nio-7777-exec-1] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:45.028  INFO 142656 --- [io-7777-exec-39] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:45.050  INFO 142656 --- [io-7777-exec-33] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:45.483  INFO 142656 --- [io-7777-exec-25] com.demo.service.ProductServiceImpl      : 库存:0
2024-01-28 15:00:47.232  INFO 142656 --- [io-7777-exec-31] com.demo.service.ProductServiceImpl      : 库存:0

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

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

相关文章

【主机漏洞扫描常见修复方案】:Tomcat安全(机房对外Web服务扫描)

文章目录 引言I SSL/TLS Not ImplementedTomcat 服务器 SSL 证书安装部署(JKS 格式)Tomcat 服务器 SSL 证书安装部署(PFX 格式)HTTP 自动跳转 HTTPS 的安全配置(可选)修复SSL证书版本低II 主机漏洞扫描常见修复方案Apache JServ protocol serviceSlow HTTP DEnial of Ser…

多楼层智能穿梭:转运机器人助力制造业转型升级

针对当前喷砂产品人工转运存在的劳动强度大、效率低、安全隐患多等问题&#xff0c;本方案提出设计一套高效、安全、多楼层自动转运系统&#xff0c;采用潜伏式转运机器人结合电梯与升降平台技术&#xff0c;实现平面类、立柱类及小工件类喷砂产品的自动化、智能化转运。 项目需…

Docker 与 Yocto

Yocto项目为什么需要Docker Yocto 项目并不直接依赖 Docker&#xff0c;但在某些情况下使用 Docker 可以为 Yocto 项目提供以下具体且实际的好处&#xff1a; 1. 环境一致性&#xff1a; Yocto 构建需要一个稳定且一致的开发环境。不同的 Linux 发行版可能会有不同的库版本、…

深入探索电能消耗数据:基于机器学习的分析与洞察

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

Java | Leetcode Java题解之第504题七进制数

题目&#xff1a; 题解&#xff1a; class Solution {public String convertToBase7(int num) {if (num 0) {return "0";}boolean negative num < 0;num Math.abs(num);StringBuffer digits new StringBuffer();while (num > 0) {digits.append(num % 7);…

【数据结构】包装类简单认识泛型-Java

包装类 在Java中&#xff0c;由于基本类型不是继承自Object&#xff0c;为了在泛型代码中可以支持基本类型&#xff0c;Java给每个基本类型都给了一个包装类型 基本数据类型和对应的包装类 基本数据类型包装类ByteByteshortShortint Integer longLongfloatFloatdoubleDoublec…

wordcloud 字体报错

wordcloud 字体报错 词云库报错&#xff1a;Only supported for TrueType fonts字体文件问题pillow版本的问题wordcloud版本问题&#xff08;我的最终解决方案&#xff09; 词云库报错&#xff1a;Only supported for TrueType fonts 字体文件问题 解决方法 写绝对路径 &…

【故障解决】麒麟系统2403用户帮助手册点击无反应的解决方法

往期好文&#xff1a;【系统配置】命令行修改统信UOS的grub启动延时 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于如何解决麒麟系统2403版本中用户帮助手册点击无反应问题的文章。很多使用麒麟系统的小伙伴可能遇到过点击“用户帮助手册”后没有任何响应的情况…

【Linux学习】(3)Linux的基本指令操作

前言 配置Xshell登录远程服务器Linux的基本指令——man、cp、mv、alias&which、cat&more&less、head&tail、date、cal、find、grep、zip&tar、bc、unameLinux常用热键 一、配置Xshell登录远程服务器 以前我们登录使用指令&#xff1a; ssh 用户名你的公网…

gorm.io/sharding改造:赋能单表,灵活支持多分表策略(下)

背景 分表组件改造的背景&#xff0c;我在这篇文章《gorm.io/sharding改造&#xff1a;赋能单表&#xff0c;灵活支持多分表策略&#xff08;上&#xff09;》中已经做了详细的介绍——这个组件不支持单表多个分表策略&#xff0c;为了突破这个限制做的改造。 在上一篇文章中&…

机器学习基础:算法如何让 AI 自我学习

大家好&#xff0c;我是Shelly&#xff0c;一个专注于输出AI工具和科技前沿内容的AI应用教练&#xff0c;体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具&#xff0c;拥抱AI时代的到来。 AI工具集1&#xff1a;大厂AI工具【共23款…

vue3+vue-baidu-map-3x 实现地图定位

文档地址&#xff1a;一个是2一个是3 https://dafrok.github.io/vue-baidu-map/#/zh/index vue-baidu-map-3x 1.首先要到百度地图开放平台上建一个账号&#xff0c;如果有百度账号可以直接登录百度地图-百万开发者首选的地图服务商,提供专属的行业解决方案 2.点击控制台&am…

ThreadLocal内存泄漏面试题

一、ThreadLocal内部结构 首先更好的说明ThreadLocal内存泄露的场景&#xff0c;以及具体的原因&#xff0c;先来了解下ThreadLocal的内部结构&#xff0c;如图1所示。 可以看到&#xff0c;ThreadLocal对象是存储在每个Thread线程内部的ThreadLocalMap中的&#xff0c;并且在…

行列式-常山赵子龙

终于知道这类题怎么写了 两个条件都要用到 要计算&#xff0c;减少直觉

【加密系统】华企盾DSC服务台提示:请升级服务器,否则可能导致客户端退回到旧服务器的版本

华企盾DSC服务台提示&#xff1a;请升级服务器&#xff0c;否则可能导致客户端退回到旧服务器的版本 产生的原因&#xff1a;控制台版本比服务器高导致控制台出现报错 解决方案 方法&#xff1a;将控制台回退到原来的使用版本&#xff0c;在控制台负载均衡查看连接该服务器各个…

图像分割-DeepLab

DeepLabV3源码链接&#xff1a;https://github.com/bubbliiiing/deeplabv3-plus-pytorch&#xff08;打不开私信我获取&#xff09; 一、简介 一般的模型如Unet一般用于医学领域&#xff0c;小目标&#xff0c;如细胞分割。 为了增大感受野&#xff08;从而更好的获得全局特征…

LeetCode 18.四数之和

LeetCode 18.四数之和 C 思路&#x1f9d0;&#xff1a; 由题意得&#xff0c;四个数组里面的整数相加需要得到target这个目标值&#xff0c;且结果不能重复&#xff0c;那么我们可以用排序双指针的方式进行解答&#xff0c;将该数组变为升序数组&#xff0c;然后固定左边两个数…

建站工具Halo

建站工具Halo 项目及文档快速体验启动成功 类似wordpress的建站工具&#xff0c;使用java技术栈Springboot开发&#xff0c;对java开发者友好。 项目及文档 https://github.com/halo-dev/halo 快速体验 为了快速体验&#xff0c;直接使用docker compose部署。也可在源码基础…

人工智能+医学

医学影响的内型&#xff1a;(X光片、计算机断层扫描、磁共振成像、超声波&#xff09; ITK snap医学图像读取 医学影像领域常见任务: 图像分类、语义分割、疾病预测、目标检测、图像配准、图像生成(应用少)、图像增强、生成放射学报告。 需要有很强的可解释…

指针进阶(三)(C 语言)

目录 一、回调函数二、快速排序函数 qsort1. qsort() 函数原型2. 使用 qsort() 函数 三、仿照 qsort 函数设计一个可以排序任意类型数组的冒泡函数1. 函数原型2. 函数设计思路 一、回调函数 在 C 语言中&#xff0c;回调函数是一种通过函数指针调用的函数&#xff0c;也就是一…