redis:六、数据过期删除策略(惰性删除、定期删除)和基于redisson实现的分布式锁(看门狗机制、主从一致性)和面试模板

本文主要是介绍redis:六、数据过期删除策略(惰性删除、定期删除)和基于redisson实现的分布式锁(看门狗机制、主从一致性)和面试模板,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

数据过期删除策略

Redis的过期删除策略:惰性删除 + 定期删除两种策略进行配合使用

惰性删除

惰性删除:设置该key过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key

优点 :对CPU友好,只会在使用该key时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查
缺点 :对内存不友好,如果一个key已经过期,但是一直没有使用,那么该key就会一直存在内存中,内存永远不会释放。

定期删除

定期删除:每隔一段时间,我们就对一些key进行检查,删除里面过期的key(从一定数量的数据库中取出一定数量的随机key进行检查,并删除其中的过期key)。

定期清理有两种模式:
SLOW模式是定时任务,执行频率可以通过修改配置文件redis.conf 来调整。
FAST模式执行频率不固定,但两次间隔不低于2ms,每次耗时不超过1ms。

优点:可以通过限制删除操作执行的时长和频率来减少删除操作对 CPU 的影响。另外定期删除,也能有效释放过期键占用的内存。
缺点:难以确定删除操作执行的时长和频率。

面试回答模板

Redis的数据过期策略有哪些 ?

背熟以下答案,大概用时1min。

在redis中提供了两种数据过期删除策略,第一种是惰性删除,在设置该key过期时间后,我们不去管它,当需要该key时,我们再检查其是否过期,如果过期,我们就删掉它,反之返回该key。

第二种是定期删除,就是说每隔一段时间,我们就对一些key进行检查,删除里面过期的key。
定期删除存在两种模式:
SLOW模式是定时任务,任务执行频率可以通过修改配置文件redis.conf 来调整。
FAST模式执行频率不固定,但两次之间的间隔和每次耗时都有固定值。

Redis的过期删除策略实际是惰性删除和定期删除两种策略配合使用的。

分布式锁

Redis实现分布式锁主要利用Redis的setnx命令。setnx是SET if not exists(如果不存在,则 SET)的简写。

获取锁

命令:

# 添加锁,NX是互斥、EX是设置超时时间
SET lock value NX EX 10

释放锁

命令:

# 释放锁,删除即可
DEL key

基于redisson看门狗机制(锁的续期)

redis加锁时,如果不自己定义参数中的leaseTime(锁自动释放时间),或者定义的leaseTime为-1,那么就会开启看门狗机制。(不定义的话,这个线程默认的leaseTime就是30s)

boolean tryLock(long waitTime, long leaseTime, TimeUnit unit);

看门狗机制就是当一个线程A加锁成功,且达到看门狗机制的触发条件时,会额外开一个线程,一般命名为Watch dog,这个线程每隔(releaseTime/3)的时间就为A续期时间,即重置过期时间。一般这个续期时间为锁的有效时间的一半,也可以自己额外设置。
在该锁有效期间,如果有其他线程想要试图加锁,那么就会不断while循环重试。

而采用了看门狗机制的锁的释放,是需要手动完成的,释放完成后还需要通知看门狗线程。

需要注意的是,加锁、设置过期时间等操作都是基于lua脚本完成的,因为能保证操作的原子性

代码模板

public void redisLock() throws InterruptedException{RLock lock = redissonClient.getLock("heimalock");try{boolean isLock = lock.tryLock(10, TimeUnit.SECONDS);if(isLock){System.out.println("执行业务……");}}finally{lock.unlock();}
}

可重入性

锁的可重入性指的是同一个线程在持有锁的情况下,能够多次获取该锁而不会发生死锁或阻塞的情况。可重入锁的一个典型应用场景是在一个方法中调用另一个加锁的方法,譬如以下代码。如果方法A在获取锁后调用了方法B,而方法B也需要获取同一个锁,那么如果锁是可重入的,方法B可以直接获取到锁,而不会因为锁已被方法A持有而发生死锁。

public void add1(){RLock lock = redissonClient.getLock(“heimalock");boolean isLock = lock.tryLock();    //执行业务  add2();//释放锁lock.unlock();
}
public void add2(){RLock lock = redissonClient.getLock(“heimalock");boolean isLock = lock.tryLock();//执行业务//释放锁lock.unlock();
}

基于redisson实现的分布式锁是拥有可重入性的。
其中的KEY一般称为大键,可以根据自己的业务来命名。
field一般称为小键,是当前线程的唯一标识。
value记录着当前线程重入的次数。
在这里插入图片描述

主从一致性

对于多线程的主从一致性,实际上redisson没办法很好地保障。
像是原本如下运行,一个主库,两个从库,且java应用程序对主库进行加锁。
在这里插入图片描述
因为某种原因,主库短暂宕机,此时根据哨兵模式选举了下面的从库为新的主库。
此时又有个新的java应用来对这个新的主库进行加锁。那么就会出现两个线程同时持有一把锁的情况。
在这里插入图片描述

redlock红锁

为此,redisson提出了一个叫RedLock,红锁。
RedLock(红锁):不能只在一个redis实例上创建锁,应该是在多个redis实例上创建锁(n / 2 + 1),避免在一个redis实例上加锁。即,在超过一半的实例上进行加锁。但是这种机制实现复杂,性能较差,运维起来也很繁琐。所以实际开发中很少用。

AP思想和CP思想

综上,对于多线程的主从一致性,实际上redis没办法很好地保障。因为redis本身是AP思想。

AP思想(可用性与分区容忍):
AP思想注重系统的可用性和分区容忍性,即在遇到网络分区或节点故障的情况下,系统仍然能够提供服务并保持可用性。这意味着系统可以容忍一定程度的数据不一致或冲突,以保证用户的访问体验。

如果想要强一致性,建议使用CP思想的zookeeper。

CP思想(一致性与分区容忍):
CP思想注重系统的一致性和分区容忍性,即在分布式环境中保持数据的一致性,并且即使发生网络分区,系统也能保持一致性。这种设计思想追求强一致性,确保所有节点中的数据都是一致的,但可能会导致一些节点不可用。

面试回答模板

Redis分布式锁如何实现 ?

候选人:嗯,在redis中提供了一个命令setnx(SET if not exists)

由于redis的单线程的,用了命令之后,只能有一个客户端对某一个key设置值,在没有过期或删除key的时候是其他客户端是不能设置这个key的

面试官:好的,那你如何控制Redis实现分布式锁有效时长呢?

候选人:嗯,的确,redis的setnx指令不好控制这个问题,我们当时采用的redis的一个框架redisson实现的。

在redisson中需要手动加锁,并且可以控制锁的失效时间和等待时间,当锁住的一个业务还没有执行完成的时候,在redisson中引入了一个看门狗机制,就是说每隔一段时间就检查当前业务是否还持有锁,如果持有就增加加锁的持有时间,当业务执行完成之后需要使用释放锁就可以了

还有一个好处就是,在高并发下,一个业务有可能会执行很快,先客户1持有锁的时候,客户2来了以后并不会马上拒绝,它会自旋不断尝试获取锁,如果客户1释放之后,客户2就可以马上持有锁,性能也得到了提升。

面试官:好的,redisson实现的分布式锁是可重入的吗?

候选人:嗯,是可以重入的。这样做是为了避免死锁的产生。这个重入其实在内部就是判断是否是当前线程持有的锁,如果是当前线程持有的锁就会计数,如果释放锁就会在计算上减一。在存储数据的时候采用的hash结构,大key可以按照自己的业务进行定制,其中小key是当前线程的唯一标识,value是当前线程重入的次数

面试官:redisson实现的分布式锁能解决主从一致性的问题吗

候选人:这个是不能的,比如,当线程1加锁成功后,master节点数据会异步复制到slave节点,此时当前持有Redis锁的master节点宕机,slave节点被提升为新的master节点,假如现在来了一个线程2,再次加锁,会在新的master节点上加锁成功,这个时候就会出现两个节点同时持有一把锁的问题。

我们可以利用redisson提供的红锁来解决这个问题,它的主要作用是,不能只在一个redis实例上创建锁,应该是在多个redis实例上创建锁,并且要求在大多数redis节点上都成功创建锁,红锁中要求是redis的节点数量要过半。这样就能避免线程1加锁成功后master节点宕机导致线程2成功加锁到新的master节点上的问题了。

但是,如果使用了红锁,因为需要同时在多个节点上都添加锁,性能就变的很低了,并且运维维护成本也非常高,所以,我们一般在项目中也不会直接使用红锁,并且官方也暂时废弃了这个红锁

面试官:好的,如果业务非要保证数据的强一致性,这个该怎么解决呢?

**候选人:**嗯~,redis本身就是支持高可用的,做到强一致性,就非常影响性能,所以,如果有强一致性要求高的业务,建议使用zookeeper实现的分布式锁,它是可以保证强一致性的。

这篇关于redis:六、数据过期删除策略(惰性删除、定期删除)和基于redisson实现的分布式锁(看门狗机制、主从一致性)和面试模板的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/511180

相关文章

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

在Linux中改变echo输出颜色的实现方法

《在Linux中改变echo输出颜色的实现方法》在Linux系统的命令行环境下,为了使输出信息更加清晰、突出,便于用户快速识别和区分不同类型的信息,常常需要改变echo命令的输出颜色,所以本文给大家介... 目python录在linux中改变echo输出颜色的方法技术背景实现步骤使用ANSI转义码使用tpu

Knife4j+Axios+Redis前后端分离架构下的 API 管理与会话方案(最新推荐)

《Knife4j+Axios+Redis前后端分离架构下的API管理与会话方案(最新推荐)》本文主要介绍了Swagger与Knife4j的配置要点、前后端对接方法以及分布式Session实现原理,... 目录一、Swagger 与 Knife4j 的深度理解及配置要点Knife4j 配置关键要点1.Spri

Python使用python-can实现合并BLF文件

《Python使用python-can实现合并BLF文件》python-can库是Python生态中专注于CAN总线通信与数据处理的强大工具,本文将使用python-can为BLF文件合并提供高效灵活... 目录一、python-can 库:CAN 数据处理的利器二、BLF 文件合并核心代码解析1. 基础合

Python使用OpenCV实现获取视频时长的小工具

《Python使用OpenCV实现获取视频时长的小工具》在处理视频数据时,获取视频的时长是一项常见且基础的需求,本文将详细介绍如何使用Python和OpenCV获取视频时长,并对每一行代码进行深入解析... 目录一、代码实现二、代码解析1. 导入 OpenCV 库2. 定义获取视频时长的函数3. 打开视频文

golang版本升级如何实现

《golang版本升级如何实现》:本文主要介绍golang版本升级如何实现问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录golanwww.chinasem.cng版本升级linux上golang版本升级删除golang旧版本安装golang最新版本总结gola

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具