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 相关底层原理 我们就介绍到这里 具体运用我们敬请期待

相关推荐
无关868819 分钟前
Redis Bitmaps 用户签到系统设计方案
数据库·redis·缓存
江华森27 分钟前
FastAPI 极速开发指南 — 从零到生产级 API 实战
数据库·fastapi
小小工匠27 分钟前
Redis - 如何使用 Redis 实现分布式锁
redis·性能优化·集群·并发
linux修理工1 小时前
使用codebuddy学习kafka
分布式·学习·kafka
阿 才1 小时前
跟文件系统(busybox)的构建
大数据·hadoop·分布式
老纪2 小时前
Redis分布式锁进第九零篇
数据库·redis·分布式
haven-8522 小时前
MySQL事务ACID、隔离级别、MVCC、幻读解决
数据库·mysql
Amy187021118232 小时前
分布式光伏防孤岛保护:技术逻辑、标准演进与工程实践全解析
分布式
小高学习java2 小时前
事务的边界问题,如何判断数据回滚时机。
java·数据库·后端
ACP广源盛139246256733 小时前
IX7008 PCIe 交换芯片@ACP#RTX Spark 经济型 8 口扩展芯片(对比 ASM1806)
大数据·人工智能·分布式·嵌入式硬件·gpt·spark·电脑