一文拿捏分布式协调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.hqwc.cn/news/124384.html

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

相关文章

【多模态融合】TransFusion学习笔记(1)

工作上主要还是以纯lidar的算法开发,部署以及系统架构设计为主。对于多模态融合(这里主要是只指Lidar和Camer的融合)这方面研究甚少。最近借助和朋友们讨论论文的契机接触了一下这方面的知识&#xff0c;起步是晚了一点&#xff0c;但好歹是开了个头。下面就借助TransFusion论文…

一键智能视频语音转文本——基于PaddlePaddle语音识别与Python轻松提取视频语音并生成文案

前言 如今进行入自媒体行业的人越来越多&#xff0c;短视频也逐渐成为了主流&#xff0c;但好多时候是想如何把视频里面的语音转成文字&#xff0c;比如&#xff0c;录制会议视频后&#xff0c;做会议纪要&#xff1b;比如&#xff0c;网课教程视频&#xff0c;想要做笔记&…

第 4 章 串(图书关键字索引表实现)

1. 背景说明 需要从书目文件中获取其关键字及对应的书号索引 bookInfo.txt 005 Computer Data Structures 010 Introduction to Data Structures 023 Fundamentals of Data Structures 034 The Design and Analysis of Computer Algorithms 050 Introduction to Numerical Anal…

Audacity 使用教程:轻松录制、编辑音频

Audacity 使用教程&#xff1a;轻松录制、编辑音频 1. 简介 Audacity 是一款免费、开源且功能强大的音频录制和编辑软件。它适用于 Windows、Mac 和 Linux 等多种操作系统&#xff0c;适合音乐制作、广播后期制作以及普通用户进行音频处理。本教程将带领大家熟悉 Audacity 的…

【OSCAR开源产业大会分论坛】开源大模型走向何方?

再过俩月&#xff0c;ChatGPT 即将迎来推出一周年纪念日。作为开历史先河的 AI 大模型&#xff0c;ChatGPT 像一针猛戳进千行百业中枢神经的兴奋剂&#xff0c;在全球掀起空前绝后的 AI 军备竞赛热潮。 近一年来&#xff0c;我们看到 GPT-3.5 完成向多模态的 GPT-4 进化&#x…

AWS-Lambda之导入自定义包-pip包

参考文档&#xff1a; https://repost.aws/zh-Hans/knowledge-center/lambda-import-module-error-python https://blog.csdn.net/fxtxz2/article/details/112035627 简单来说,以 " alibabacloud_dyvmsapi20170525 " 包为例 ## 创建临时目录 mkdir /tmp cd ./tmp …

网络基础(了解网络知识的前提)

前言 在正式学习网络之前&#xff0c;我们需要了解的一些关于计算机网络的基本知识&#xff0c;本文主要阐述这些基本知识&#xff0c;带着大家一步一步迈进互联网网络的世界&#xff1b; 一、局域网与广域网的概念 在正式了解这些概念的前提是我们要搞懂网络出现的意义&#x…

Leetcode202. 快乐数

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&#xff0…

车牌文本检测与识别:License Plate Recognition Based On Multi-Angle View Model

论文作者&#xff1a;Dat Tran-Anh,Khanh Linh Tran,Hoai-Nam Vu 作者单位&#xff1a;Thuyloi University;Posts and Telecommunications Institute of Technology 论文链接&#xff1a;http://arxiv.org/abs/2309.12972v1 内容简介&#xff1a; 1&#xff09;方向&#x…

vscode 乱码解决

windows 10 系统 vs code 编译运行和调试 C/C_vscode windows编译_雪的期许的博客-CSDN博客 VS Code默认文件编码时UTF-8&#xff0c;这对大多数情况是没有问题的&#xff0c;却偏偏对C/C有问题。如果以UTF-8编码保存C/C代码&#xff0c;那么只能输出英文&#xff0c;另外使用…

Hono——一个小型,简单且超快的Edges Web框架

Hono - [炎]在日语中的意思是火焰&#x1f525; - 是一个小型&#xff0c;简单且超快的Edges Web框架。它适用于任何JavaScript运行时&#xff1a;Cloudflare Workers&#xff0c;Fastly ComputeEdge&#xff0c;Deno&#xff0c;Bun&#xff0c;Vercel&#xff0c;Netlify&…