redis分布式是如何实现的(面试版)

需要结合项目中的业务进行回答,通常情况下,分布式锁使用的场景集群情况下的定时任务、抢单、幂等性场景。

下面先来看一个抢卷场景:

以下情况会出现超卖情况:

因为线程会交替执行,所以线程查询优惠价的数据量后,线程2又查询优惠券的数据量,此时如果优惠券总数是1,最后优惠券的数量会变成-1,出现超卖。

使用synchronized解决:

但在集群的情况下,这种方式(本地加锁)会失效,因为synchronized是本地锁,这个锁属于JVM,每个服务都有各自的JVM,它只能解决同一个JVM下线程的互斥:

此时需要加分布式锁:

redis分布式锁

什么是分布式锁:支持分布式集群环境下的锁

基于redis来实现分布式锁,底层使用的是setnx和lua脚本。

图1-1

上图中,必须设置锁的超时时间,否则当服务宕机的时候就不会释放锁了。

redisson实现的分布式锁如何合理控制锁的有效时长

继续看图1-1,因为加锁的时候给了一个失效时间,假如业务的执行时机太长,已经超出了锁的释放时间,但此时业务还没有执行完成,假如其他线程来获得锁就会获得成功

出现这种情况后,可以给锁续期:redisson实现的分布式锁-执行流程:

  1. 有一个线程(线程1)过来,它获取锁并加锁成功后,然后就会去操作redis
  2. 加锁成功后,会另开一个线程(Watch dog)监控 持有锁的线程给持有锁的线程 增加锁的持有时间**(续期)。续期的规则为每隔 releaseTime/3(releaseTime是锁的过期时间) 的时间**做一次续期,默认为10秒。
  3. 手动释放锁,手动释放锁之后,需要通知对应线程的Watch dog不需要再监听了

图2-1

假如,现在又来了一个新的线程(线程2),想获取锁,它先尝试去加锁,如果加锁成功,和 图2-1的流程是一样的,但如果没有加锁成功呢?在redisson实现的分布式锁中,它设置了一个while循环来不断的尝试去加锁,如果加锁成功了就成功了,如果线程1一直没有释放锁,线程2有一个阈值,只要循环到了阈值,线程2就会获取锁失败,这种机制会在高并发下,大程度增加分布式锁的性能:

下图为redisson的使用,所有的redisson命令基于lua脚本 完成,保证脚本执行的原子性

redisson实现的分布式锁是否可以重入

首先分析下图的代码:

  • 在add1中尝试获取了锁,再去调用add2,add又去尝试获取锁,此时都是同一个线程,可以重入。

回答:可以重入,判断是否是当前线程 ,通过线程id去判断,如果是同一个线程就可重入,否则不能

redisson中可重入的实现

使用hash类型来存储锁数据(线程的唯一标识和重入次数):

  • 每加一次锁,重入次数都会+1,每释放一次锁重入次数-1,全部释放完变成0后删除锁信息。

redisson实现的分布式锁可以保证主从一致吗

不能解决,但可以使用红锁保证主从一致,但性能太低,一般项目中用的不多,哪有服务器天天挂;如果想要保证数据的强一致性就去使用CP思想的zookeeper。

相关推荐
计算机学长felix20 分钟前
基于Django的“酒店推荐系统”设计与开发(源码+数据库+文档+PPT)
数据库·python·mysql·django·vue
ClouGence39 分钟前
Redis 双向同步如何避免循环?【附实操演示】
redis
GBASE40 分钟前
ITPUB专访南大通用——GBase 8s数据库以内核铸根基,以生态赢未来
数据库
GBASE1 小时前
GBASE南大通用技术分享:构建最优数据平台,GBase 8s数据库安装准备(二)
数据库
JAVA学习通1 小时前
【RabbitMQ】---RabbitMQ 工作流程和 web 界面介绍
分布式·rabbitmq
林熙蕾LXL1 小时前
SQL Server——基本操作
数据库·sql
GBASE1 小时前
GBASE南大通用技术分享:构建最优数据平台,GBase 8s数据库安装准备
数据库
IOT-Power1 小时前
树莓派 Ubuntu 24.04 开机换源总结
linux·数据库·ubuntu
阿华田5121 小时前
重试框架 -- Guava Retry
数据库
柠檬汁Dev2 小时前
还在等DBA给你库?我3分钟就拉起一个高可用集群
数据库·云计算·dba