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

news2024/11/20 14:31:19

 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 {
​
    @Autowired
    private 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 {
​
    @Autowired
    private BloomFilterService bloomFilterService ;
​
    @GetMapping(value = "/resetBloomFilter")
    public Result resetBloomFilter() {
        bloomFilterService.resetBloomFilter();
        return Result.ok("重置bloomfilter成功") ;
    }
​
}

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

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

相关文章

【SimpleDateFormat】线程不安全问题分析及解决方案

前言 在日常开发中&#xff0c;我们经常需要去做日期格式转换&#xff0c;可能就会用到SimpleDateFormat类。但是&#xff0c;如果使用不当&#xff0c;就很容易引发生产事故&#xff01; 1. 问题推演 1.1 初始日期工具类 刚开始的日期转换工具类可能长这样&#xff1a; p…

nodejs+vue晓海网上订餐系统elementui

管理员功能需求 管理员登陆后&#xff0c;主要模块包括首页、个人中心、用户管理、菜单信息管理等功能。 第三章 系统分析 10 3.1需求分析 10 3.2可行性分析 10 3.2.1技术可行性&#xff1a;技术背景 10 3.2.2经济可行性 11 3.2.3操作可行性&#xff1a; 11 3.3性能分析 11 3.4…

创建GCP service账号并管理权限

列出当前GCP项目的所有service account 我们可以用gcloud 命令 gcloud iam service-accounts list gcloud iam service-accounts list DISPLAY NAME EMAIL DISABLED terraform …

数据结构 1.1 初学数据结构

数据结构的基本概念 数据结构在学什么&#xff1f; 如何用程序代码把现实世界的问题信息化 如何用计算机高效处理信息从而创造价值 数据&#xff1a; 数据元素、数据项&#xff1a; 数据元素——描述一个个体 数据对象——数据元素之间具有同样的性质 同一个数据对象里的数…

BGP高级特性——4字节AS号

目录 4字节AS号 相关概念 两种过渡属性 4字节AS号的格式 4字节AS号建立邻居 4字节AS号路由传递 配置命令 4字节AS号 相比于2字节AS号&#xff0c;范围更大。由1~65535扩展到1~4294967295 支持4字节AS号的BGP设备兼容仅支持2字节AS号的BGP设备 相关概念 Speaker&#…

13链表-简单思路练习

目录 LeetCode之路——876. 链表的中间结点 分析&#xff1a; 解法一&#xff1a;常规思路 解法二&#xff1a;快慢指针 LeetCode之路——876. 链表的中间结点 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回…

详解Linux的系统调用fork()函数

在Linux系统中&#xff0c;fork()是一个非常重要的系统调用&#xff0c;它的作用是创建一个新的进程。具体来说&#xff0c;fork()函数会在当前进程的地址空间中复制一份子进程&#xff0c;并且这个子进程几乎完全与父进程相同&#xff0c;包括进程代码、数据、堆栈以及打开的文…

利用Redis实现全局唯一ID

利用Redis实现全局唯一ID 背景 场景分析&#xff1a;如果我们的id具有太明显的规则&#xff0c;用户或者说商业对手很容易猜测出来我们的一些敏感信息&#xff0c;比如商城在一天时间内&#xff0c;卖出了多少单&#xff0c;这明显不合适。 场景分析二&#xff1a;随着我们商…

怎么将本地代码文件夹通过Git 命令上传到启智平台仓库

在本地创建一个与启智平台仓库同样名字的文件夹 然后在本地文件夹右键–>选择Git Bash Here,就会打开Git命令窗口 初始化本地仓库 git init将项目文件添加到Git git add .提交更改&#xff1a; 使用以下命令提交您的更改&#xff0c;并为提交添加一条描述性的消息&#…

ArcGIS Engine:实现Shp/Mxd数据的加载、图层的简单查询

本博客参考&#xff1a;BiliBili UP主 <羊羊旸> &#xff1a; Arcgis Engine学习 目录 01 加载控件以及控件的基本信息等调整 02 编写 <菜单-地图控件> 中各个子工具的代码 2.1 加载Shapefile数据-代码 2.2 加载地图文档数据-代码 2.3 获取图层数量-代码 2.…

lv7 嵌入式开发-网络编程开发 04 IP地址与端口号

目录 1 IP地址 1.1 IP 地址及其表示方法 1.2 分类的 IP 地址 1.3 无分类编址 CIDR 1.3.1 网络前缀 1.3.2 地址块 1.3.3 地址掩码 (address mask) 1.4 IPv6 的地址 1.4.1 表示方式 1.4.2 零压缩 2 端口号 2.1 进程之间的通信 2.2 运输层的作用 2.3 屏蔽作用 2.4…

CompletableFuture 异步编排

目录 CompletableFuture 的详解代码测试配置类的引入Demo1Demo2CompletableFuture的async后缀函数与不带async的函数的区别ThreadPoolTaskExecutor 和 ThreadPoolExecutor 的区别Spring 线程池的使用业务使用多线程的原因场景一:场景二:FutureTask介绍线程池为什么要使用阻塞队…

(三) Markdown插入互联网或本地视频解决方案

前言 不论博客系统是WordPress还是Typecho&#xff0c;绕不开的是两种书写语言&#xff0c;一种称之为富文本&#xff0c;一种叫做Markdown。 Markdown有很多好处&#xff0c;也有很多坏处&#xff0c;比如Markdown本身不具备段落居中的功能&#xff0c;以及Markdown也不具有…

聊聊JAVA中的锁优化锁升级及其底层原理剖析

文章目录 1. 基础介绍java中的锁什么是锁优化和锁升级 2. Java中的锁升级过程及底层原理1. 偏向锁实现机制和原理1. 偏向锁的原理2. 偏向锁的底层实现 2. 轻量级锁1. 轻量级锁的原理2. 轻量级锁的底层实现 3. 重量级锁1. 重量级锁的原理2. 重量级锁的底层实现 3. Java中锁升级的…

selenium +IntelliJ+firefox/chrome 环境全套搭配

1第一步&#xff1a;下载IntelliJ idea 代码编辑器 2第二步&#xff1a;下载浏览器Chrome 3第三步&#xff1a;下载JDK 4第四步&#xff1a;配置环境变量&#xff08;1JAVA_HOME 2 path&#xff09; 5第五步&#xff1a;下载Maven 6第六步&#xff1a;配置环境变量&#x…

新环境下配置jupyter notebook并启动

1.先切换到我们需要使用的环境 2.安装python内核 conda install ipykernel 3.创建指定内核 ipython kernel install --user --nametensorflow2 4.运行jupyter notebook 即出现新创建的内核

计算机网络 第一章计算机网络体系结构

非常好的课程。计算机网络 //----------------------------------------------------------------------------------------------------------------// 需要清楚实体、协议、服务。 网络协议三要素&#xff0c;语法、语义、同步。

遗留系统陷入困境

当我们谈论遗留系统时&#xff0c;我们经常会想到数据中心某处的过时服务器和交换机。我们带着一种病态的迷恋阅读了有关系统性技术问题的文章&#xff0c;这些问题在假期周末困扰着其他旅行者&#xff0c;并为他们缺乏远见而摇头。 然后&#xff0c;我们坐在屏幕前&#xff0…

数据结构—栈、队列、链表

一、栈 Stack&#xff08;存取O(1)&#xff09; 先进后出&#xff0c;进去123&#xff0c;出来321。 基于数组&#xff1a;最后一位为栈尾&#xff0c;用于取操作。 基于链表&#xff1a;第一位为栈尾&#xff0c;用于取操作。 1.1、数组栈 /*** 基于数组实现的顺序栈&#…

4 Ways to Fix an Operation Did Not Complete Virus Error on Windows

文章目录 Can’t open a file on your PC? Use these methods to fix your issue. A Windows operation did not complete virus error.Mahesh Makvana / How-To Geek Readers like you help support How-To Geek. When you make a purchase using links on our site, we ma…