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

相关推荐
Amir_zy21 分钟前
Redis测试方法全攻略:冒烟、压测与稳定性验证
redis·压力测试
IvorySQL26 分钟前
PostgreSQL 日报| RI 快速路径并发读取缺陷(8 月 13 日)
数据库·postgresql
highreport1 小时前
HighReport报表工具定时调度和邮件定时发送
运维·服务器·数据库
01_ice1 小时前
数据库基础
数据库
naierfengdian1 小时前
分布式风电助力乡村能源转型的技术路径
分布式·能源
deepdata_cn1 小时前
向量数据库是非结构化数据的AI检索底座
数据库·人工智能
梁辰兴1 小时前
软件工程:数据库设计
数据库·软件工程·数据库设计·逻辑设计·概念设计·梁辰兴·物理设计
10mAh2 小时前
【Git】误删分支、reset --hard 后提交丢了怎么办?——reflog、fsck 与安全恢复实战
数据库·git·安全·回归
J_bean2 小时前
剖析 MySQL InnoDB 共享行锁 (S) & 排他行锁 (X)
数据库·mysql·共享行锁·s lock·排他行锁·x lock
Lumistory2 小时前
城市景观亮化设施维护管养的核心痛点与标准化解决方案
数据库·光照贴图