Redis 分布式锁

在分布式系统中,存在多进程多主机(每个服务器都是独立的进程),在此种情况下,多进程的运行情况是随机的,我们无法使用sychronized这类锁去控制多进程

因此我们就需要引入"分布式锁"

分布式锁的实现

在上面这张图中,当客户端进行买票操作时,会先查询余票,然后进行扣除,当没有加锁时,在第一个客户端进行操作查询到余票 还未扣除时,第二个客户端也进行买票操作,那么此时就会出现超卖情况

所谓的分布式锁 就是一个/一组单独的服务器程序,给其他的服务器提供"加锁"这样的服务

买票服务器在进行买票时,操作的过程中就需要先加锁

Redis上设置一个特殊的key-value

完成上述买票操作,再把这个key-value删除掉

如果其他服务器要进行买票操作,就会设置这个key-value 如果已经存在 就会加锁失败,至于是阻塞还是放弃 看具体策略

引入setnx

setnx这个指令的语义是不存在就设置,存在就出错

使用setnx确实可以得到加锁效果

针对解锁,就可以使用del命令来完成

但这样当某个服务器进行setnx 还未执行del 服务器挂了 那此时锁无法释放

设置过期时间

可以给sey的key设置过期时间 一旦时间到了就会自动删除

set ex nx 这样的命令来设置

校验id

因为我们此处分布式锁只是redis上的一个键值对,那么很有可能被误删,服务器1执行加锁,而服务器2执行了解锁

正常来说是不会的 但是代码总有bug

为了解决上述问题,就引入一点校验机制

1.给服务器编号,每个服务器有一个自己的身份标识

2.进行加锁的时候,设置key-value,key对应着要针对哪个资源加锁(比如车次),value就可以存储刚才服务器编号,标识当前锁是哪个服务器加上的

解锁时 就先查询所对应服务器编号,判定这个编号是否就是当前执行解锁的服务器编号,如果是执行del,如果不是 失败

引入lua脚本

在执行解锁过程中 由于是两步操作,先获取,后解锁

服务器很可能是多线程的 就会出现问题

使用事务可以解决上述问题 防止插队,但实践中往往使用的是lua脚本

可以使用lua编写一些逻辑,把这个脚本上传到redis服务器上,然后就可以让客户端来控制redis执行上述脚本

redis执行lua脚本的过程,也是原子的,相当于执行一条命令一样(实际上lua中可以 写对个命令)

引入看门狗

过期时间的续约问题

过期时间设置多少合适

*如果设置的短,可能业务执行逻辑还没执行完就释放锁了

*如果设置的太长,就也会导致锁释放不及时的问题

更好的方式是动态续约 往往需要服务器这边有个专门的线程 来进行 叫"看门狗"

初始时设置一个时间 动态续约 如果服务器挂掉 也不会一直持有锁 会随后释放

redlock算法

使用redis作为分布式锁,redis本身有没有可能挂呢,很有可能

哨兵模式中 当主节点加锁后挂了 从节点成为新的主节点 获取的有主节点的数据也会被加锁

但当主节点挂了时 从节点同步主节点数据有延迟,此时呢就会可能加锁失败

为了提高可用性,就使用了redlock算法

这样呢就提高了可用性

关于redis 分布式锁呢 我们就探讨到这里

至此Redis 相关底层原理 我们就介绍到这里 具体运用我们敬请期待

相关推荐
2501_944521002 小时前
rn_for_openharmony商城项目app实战-商品评价实现
javascript·数据库·react native·react.js·ecmascript·harmonyos
冉冰学姐2 小时前
SSM心理健康系统59q3n(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架应用·心理健康系统·心理文章
heartbeat..2 小时前
零基础学 SQL:DQL/DML/DDL/DCL 核心知识点汇总(附带连接云服务器数据库教程)
java·服务器·数据库·sql
傻啦嘿哟3 小时前
Python中的@property:优雅控制类成员访问的魔法
前端·数据库·python
岁岁种桃花儿3 小时前
MySQL 8.0 基本数据类型全面解析
数据库·mysql·数据库开发
用户427007458384 小时前
第二节:使用Mongoose连接数据库
数据库
煎蛋学姐4 小时前
SSM协同过滤的视频推荐系统s04mp(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·用户管理·协同过滤·ssm 框架·视频推荐系统
马克学长4 小时前
SSM薪酬管理系统b26z4(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架·薪酬管理系统
胡萝卜的兔4 小时前
ThinkPHP6.0 Redis 延迟队列 + 定时任务 实现超时取消订单完整部署脚本
数据库·redis·缓存