一文拿捏分布式协调Redis客服端-Redisson

 Redisson

1.介绍

Redisson - 是一个高级的分布式协调Redis客服端 , 专注于分布式系统开发,让用户可以在分布式系统中很方便的去使用Redis。

2.相关使用

1.加锁

//底层是lua脚本保证了加锁的原子性
// 一直等待获取锁,直到获取到锁为止! 默认锁的存活时间为30s 
lock.lock(); 
// 一直等待获取锁,并且显式的指定锁的过期时间 
lock.lock(10 , TimeUnit.SECONDS); 
// 尝试获取一次锁,如果可以获取到锁就返回true,否则返回false, 默认情况下锁的过期时间为30s 
lock.tryLock(); 
// 尝试获取一次锁,指定加锁的等待超时时间为3s, 如果在3s内获取到了锁,那么此时就返回true,否则返回false, 默认情况下锁的过期  时间为30s 
boolean tryLock = lock.tryLock(3, 20, TimeUnit.SECONDS); 
//通过如下方式获取的锁是可重入锁: 
RLock lock = redissonClient.getLock(”redisson-lock”);

2.释放锁

加解锁必须成对出现

🌟面试题
1.在你的项目开发的过程中有没有遇到过一些技术难点,你是怎么解决的?

有,在我们的系统使用到了Redisson框架,主要用的就是它里面分布式锁的功能,在Redssion框

架中分布式锁的实现是存在续期机制的,续期机制底层是通过一个异步线程进行执行的。由一次我

们在写代码的时候由于释放锁的代码没有写到finally语句块中,业务代码执行的时候产生了异常,

锁的续期代码照样执行,就导致其他的线程获取不到分布式锁就出现了死锁现象。

2.🌟死锁产生的条件,如何避免?
  1. 互斥条件

  2. 占有且等待

  3. 不可抢占

  4. 循环等待

死锁一旦发生,其实基本上就很难人为干预解决他,所有我们只能尽可能的规避他上面提到的四个

条件,只要同时满足了就会触发死锁,我们只需打破其中任意一条,死锁自然也就不会存在了

举例说明:

第一条:互斥条件这个作为锁所必须的条件,无法干预

第二条:破坏占有并等待==>可以一次性申清所需的所有资源此时就不存在等待的问题

第三条:当其中一个线程再去申请资源的时候,如果申请不到

第四条:破坏循环等待==>给系统的所有资源编号,规定进程请求所需资源的顺序必须按照资源的编号依次进行

3.🌟如何检测(死锁)出来的?
检测死锁的三种方法
  1. 使用图形化工具jconsole.exe

  2. jps -l 查看线程信息 ------> 使用 jstack (id)

  3. 使用jprofiler工具

/*** @author: Niimp* @date: 2023/8/2 14:46* @statement:  测试代码(死锁)* 检查死锁的三种方法:* JDK自带:*    1.使用图形化工具jconsole.exe*    2.jps -l 查看线程信息*      使用 jstack (id)* 3.使用jprofiler工具**/
package com.niimpday1;
​
import java.util.concurrent.TimeUnit;
​
class DeadLock {final Object resource1 = new Object();final Object resource2 = new Object();
​public void DeadLock(){new Thread(() -> {synchronized (resource1){System.out.println(Thread.currentThread().getName() + "获取resource1");try {TimeUnit.SECONDS.sleep(1);System.out.println(Thread.currentThread().getName() + "尝试获取resource2");synchronized (resource2){System.out.println(Thread.currentThread().getName() + "获取resource2");}} catch (InterruptedException e) {throw new RuntimeException(e);}}}, "A").start();
​new Thread(() -> {synchronized (resource2){System.out.println(Thread.currentThread().getName() + "获取resource2");try {TimeUnit.SECONDS.sleep(1);System.out.println(Thread.currentThread().getName() + "尝试获取resource1");synchronized (resource1){System.out.println(Thread.currentThread().getName() + "获取resource1");}} catch (InterruptedException e) {throw new RuntimeException(e);}}}, "B").start();}
}
​
public class Test9 {public static void main(String[] args) {new DeadLock().DeadLock();}
}

3.锁续期

  1. 当用户没有指定锁的超时时间的时候,那么此时Redssion框架会自动给锁进行续期。

  2. 续期规则:当锁的经过了设置时间的1/3的时候,会自动续期到默认的30s(自定义设置锁的过期时间会使锁续期机制失效)

  3. 续期原理:通过一个定时任务进行实现,底层通过一个异步线程完成锁的续期

4.信号量

进行限流

RSemaphore semaphore = null ;
@PostConstruct
public void init() {semaphore = redissonClient.getSemaphore("test-semaphore");semaphore.addPermits(2);        // 分配两个许可证
}
@GetMapping(value = "/semaphore")
public Result semaphore() throws InterruptedException {semaphore.acquire();  // 申请许可证log.info(Thread.currentThread().getName() + "----> 申请到了一个许可证...");Thread.sleep(500);semaphore.release();log.info(Thread.currentThread().getName() + "----> 归还了一个许可证....");return Result.ok() ;
}

5.其他锁

//1、公平锁:
RLock lock = redisson.getFairLock(”myLock”); 
//2、读写锁: 
RReadWriteLock rwlock = redisson.getReadWriteLock(”myLock”); 
//读写锁的特性:读读兼容、读写互斥、写写互斥、写读互斥

6.分布式布隆过滤器

本地布隆过滤器的弊端:集群环境太浪费系统资源、集群环境也不容易对布隆过滤器进行维护

1.Redssion中提供的分布式布隆过滤器的使用
// 获取一个分布式的布隆过滤器(RedissonClient)
RBloomFilter<V> getBloomFilter(String name);
​
// 初始化分布式的布隆过滤器(RBloomFilter)
boolean tryInit(long expectedInsertions, double falseProbability);
​
// 判断布隆过滤器中是否存在数据(RBloomFilter)
boolean contains(T object);
​
// 判断布隆过滤器是否存在(RBloomFilter)
boolean isExists();
​
// 向布隆过滤器中进行数据的添加
boolean add(T object);

代码实现:

// com.atguigu.gmall.product.service.impl.SkuInfoServiceImpl
@Autowired
private RedissonClient redissonClient ;
​
// 将BloomFilter过滤器的初始化动作放到service-product中更为合适,不用发起远程调用
@PostConstruct
public void initBloomFilter() {
​// 分布式布隆过滤器的使用RBloomFilter<Long> bloomFilter = redissonClient.getBloomFilter(GmallConstant.DIS_BLOOM_FILTER);if(!bloomFilter.isExists()) {bloomFilter.tryInit(1000000 , 0.00001) ;List<Long>  skuIds = skuInfoMapper.findAllSkuIds() ;skuIds.forEach( skuId -> {bloomFilter.add(skuId) ;});log.info("分布式布隆过滤器,判断49号商品是否存在:" + bloomFilter.contains(49L) + "判断99号商品是否存在: " + bloomFilter.contains(99L));}}
​
// 添加bloomFilter常量值到GmallConstant中
public static final String DIS_BLOOM_FILTER = "sku-bloom-filter" ;
2. 布隆过滤器重置
1.数据库中的数据发送变更以后bloomFilter是否需要变更?
  1. 新增数据:直接向bloom过滤器中添加新的数据即可

  2. 修改数据: 不用对bloomFilter进行变更(布隆过滤其中存储的是id)

  3. 删除数据:需要重置bloom过滤器的值(删除原来的bloom过滤器创建新的bloom过滤器)

2.🌟布隆过滤器重置步骤
  1. 创建一个新的布隆过滤器 (sku:bloom:filter:new)

  2. 删除之前的布隆过滤器(sku:bloom:filter)

  3. 对新创建的布隆过滤器进行重命名,把新布隆过滤器的名称改成之前的布隆过滤器的名称

需要保证:删除和重命操作的原子性(使用lua脚本)

3.🌟布隆过滤器重置时机

看业务对数据的时效性要求

1.业务对数据要求高时效性:需要在删除数据的时候调用重置布隆过滤器的方法完成布隆过滤器的

重置,虽然会浪费一些性能,但也得这么做

2.业务对数据的时效性要求不高:使用定时任务实现布隆过滤器的重置

1.定时任务

1、定时任务触发(spring task)

// com.atguigu.gmall.product.task
@Service
@Slf4j
public class ResetBloomFilterTimeTask {
​@Autowiredprivate BloomFilterService bloomFilterService ;
​@Scheduled(cron = "0 0 3 */7 * ?")public void resetBloomFilterTimeTask() {log.info("重置bloom过滤器定时任务执行了....");bloomFilterService.resetBloomFilter();}
​
}
​
// 启动类添加@EnableScheduling注解

cron表达式:命令定时执行方式_云服务器 ECS-阿里云帮助中心

2、提供一个接口,在后台开放调用该接口的功能

// com.atguigu.gmall.product.controller
@RestController
@RequestMapping(value = "/admin/product")
public class BloomFilterController {
​@Autowiredprivate BloomFilterService bloomFilterService ;
​@GetMapping(value = "/resetBloomFilter")public Result resetBloomFilter() {bloomFilterService.resetBloomFilter();return Result.ok("重置bloomfilter成功") ;}
​
}

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

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

相关文章

Maven - MacOS 快速安装

配置信息 Maven 版本&#xff1a;3.6.3Maven 地址&#xff1a;Index of /dist/maven/maven-3IDEA&#xff1a;2023 Tips&#xff1a;Maven 版本最好不要超过 3.8.0&#xff0c;最新版 Maven 会不兼容一些配置信息。上面的 Maven 地址里可以选择自己想下载的版本&#xff08;这…

STM32三种开发方式及标准库和HAL库的编程差异

三种开发方式 STM32基于标准库函数和HAL库编程差异_stm32库函数和hal库-CSDN博客本文目的是以串口通信来简要分析STM32使用标准库函数和HAL库函数编程的差异。目录&#xff08;一&#xff09;开发方式1.配置寄存器2.库函数3.HAL库&#xff08;二&#xff09;库函数与HAL库对比…

Git小书系列笔记

Git准备 首先根据自己的系统安装git&#xff0c;安装成功后可以通过如下指令查看git版本。 使用Git之前&#xff0c;需要配置用户名称和电子邮件。 1.设置全局的用户名和电子邮件 git config --global user.name "Your Name" git config --global user.email &quo…

Spring的注解开发-注解原理解析-xml方式/注解方式组件扫描

目录 Spring注解的解析原理 xml配置组件扫描 注解方式配置组件扫描 原理图 yysy&#xff0c;没有搞太明白&#xff0c;真的复杂&#xff0c;欢迎大佬留言解惑 Spring注解的解析原理 使用Component等注解配置完毕后&#xff0c;要配置组件扫描才能使注解生效 xml配置组件扫…

driver.js 扩展下次“不再提示”功能

文档地址&#xff1a;https://github.com/kamranahmedse/driver.js 官方demo&#xff1a;https://kamranahmed.info/driver.js/ /*** Title: 页面引导 ……* Author: JackieZheng* Date: 2023-08-16 10:43:31* LastEditTime: 2023-08-16 10:55:08* LastEditors:* Description:*…

Nginx限流熔断

一、Nginx限流熔断 Nginx 是一款流行的反向代理和负载均衡服务器&#xff0c;也可以用于实现服务熔断和限流。通过使用 Nginx 的限流和熔断模块&#xff0c;比如&#xff1a;ngx_http_limit_req_module 和 ngx_http_limit_conn_module&#xff0c;可以在代理层面对服务进行限流…

【JavaEE】synchronized 原理

文章目录 前言synchronized 的加锁过程1.无锁 -> 偏向锁2. 偏向锁 -> 轻量级锁3. 轻量级锁 -> 重量级锁 锁的优化操作1. 锁消除2. 锁粗化 相关面试题 前言 前面我们学习了关于JavaEE多线程方面的锁策略以及 synchronized 分别对应哪些锁策略&#xff0c;并且我们还了…

JMeter性能测试

性能测试前言 老师开局一句话&#xff1a;性能测试和你会不会JMeter一点关系没有…… 作者坚持技多不压身的原则&#xff0c;还是多学一点JMeter吧&#xff0c;看老师到底要怎么讲下去&#xff0c;什么并发量、吞吐量啥的…… 性能测试的核心思想&#xff1a;在于创造大量并发去…

消息队列-RabbitMQ(二)

接上文《消息队列-RabbitMQ&#xff08;一&#xff09;》 Configuration public class RabbitMqConfig {// 消息的消费方json数据的反序列化Beanpublic RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(ConnectionFactory connectionFactory){Simple…

Open Cascade旋转变换平行线

在本人开发的弯管自动CAM软件中&#xff0c;有一个问题一直没有解决&#xff0c;就是180度平行管路需要做角度微调&#xff0c;以便进行YBC预览。研究了一番后&#xff0c;搞定了这个问题&#xff0c;关键在于采用OCC库实现拓扑变换。 本文将介绍如何使用OpenCASCADE库来实现平…

3.物联网射频识别,(高频)RFID应用ISO14443-2协议,(校园卡)Mifare S50卡

问题&#xff1a; 1) 14443协议&#xff0c;RFID标签的默认通信速率是 106kbps&#xff0c;也可以通过协商&#xff0c;调整为 &#xff08;fc/6413.56M/64&#xff09;212、424、 848kbps。 2) 14443-3 A类卡&#xff0c;上电后&#xff0c;读写器发送REQA命令&#xff0c;标签…

激光雷达中实现F-P标准具高热稳定性的帕尔贴精密温控解决方案

摘要&#xff1a;法布里-珀罗标准具作为一种具有高温度敏感性的精密干涉分光器件&#xff0c;在具体应用中对热稳定性具有很高的要求&#xff0c;如温度波动不能超过0.01℃&#xff0c;为此本文提出了相应的高精度恒温控制解决方案。解决方案具体针对温度控制精度和温度均匀性控…

计算机竞赛 题目: 基于深度学习的疲劳驾驶检测 深度学习

文章目录 0 前言1 课题背景2 实现目标3 当前市面上疲劳驾驶检测的方法4 相关数据集5 基于头部姿态的驾驶疲劳检测5.1 如何确定疲劳状态5.2 算法步骤5.3 打瞌睡判断 6 基于CNN与SVM的疲劳检测方法6.1 网络结构6.2 疲劳图像分类训练6.3 训练结果 7 最后 0 前言 &#x1f525; 优…

angularjs开发环境搭建

Angularjs是一个前端页面应用开发框架&#xff0c;其使用TypeScript作为开发语言&#xff0c;Angularjs的特性包括&#xff0c;使用组件、模板以及依赖注入的开发框架构建可扩展的web应用&#xff0c;使用易于集成的类库支持页面路由、页面表单、前后端接口交互等各种不同特性&…

JVM:经典垃圾收集器

经典垃圾收集器 如果说收集算法是内存回收的方法论&#xff0c;那垃圾收集器就是内存回收的实践者 《Java虚拟机规范》中对垃圾收集器应该如何实现并没有做出任何规定&#xff0c;因此不同的厂商、不同版本的虚拟机所包含的垃圾收集器都可能会有很大差别&#xff0c;不同的虚拟…

【Java】微服务——Nacos注册中心

目录 1.Nacos快速入门1.1.服务注册到nacos1&#xff09;引入依赖2&#xff09;配置nacos地址3&#xff09;重启 2.服务分级存储模型2.1.给user-service配置集群2.2.同集群优先的负载均衡 3.权重配置4.环境隔离4.1.创建namespace4.2.给微服务配置namespace 5.Nacos与Eureka的区别…

Day 04 python学习笔记

Python数据容器 元组 元组的声明 变量名称&#xff08;元素1&#xff0c;元素2&#xff0c;元素3&#xff0c;元素4…….&#xff09; &#xff08;元素类型可以不同&#xff09; eg: tuple_01 ("hello", 1, 2,-20,[11,22,33]) print(type(tuple_01))结果&#x…

uniapp实现微信小程序隐私协议组件封装

uniapp实现微信小程序隐私协议组件封装。 <template><view class"diygw-modal basic" v-if"showPrivacy" :class"showPrivacy?show:" style"z-index: 1000000"><view class"diygw-dialog diygw-dialog-modal bas…

求各区域热门商品Top3 - HiveSQL

背景&#xff1a;这是尚硅谷SparkSQL练习题&#xff0c;本文用HiveSQL进行了实现。 数据集&#xff1a;用户点击表&#xff0c;商品表&#xff0c;城市表 题目: ① 求每个地区点击量前三的商品&#xff1b; ② 在①的基础上&#xff0c;求出每个地区点击量前三的商品后&a…

MySQL-MVCC(Multi-Version Concurrency Control)

MySQL-MVCC&#xff08;Multi-Version Concurrency Control&#xff09; MVCC&#xff08;多版本并发控制&#xff09;&#xff1a;为了解决数据库并发读写和数据一致性的问题&#xff0c;是一种思想&#xff0c;可以有多种实现方式。 核心思想&#xff1a;写入时创建行的新版…