Redis分布式锁

线程安全->锁,多线程并发执行的时候,执行先后的顺序,不确定,随机性->需要保证程序在任意执行顺序下,执行逻辑都是ok的,之前学过的锁,mutex,synchronized本质上只能在一个进程内部生效,分布式系统中,是有很多进程的(每个服务器,都是独立的进程)

因此,之前的锁,就难以对现在的分布式系统中的多个进程之间产生制约,因此,分布式系统中,多个进程之间的执行顺序也是不确定的,引入分布式锁解决上述问题。

买票服务器,再进行买票操作过程中,就需要先加锁(往redis上设置一个特殊的key-value

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

其他服务器也想买票,也去redis上尝试设置key-value,如果发现了key-value已经存在,就认为加锁失败(放弃/阻塞,就看具体的实现策略了)就可以保证第一个服务器执行"查询->更新"过程中,第二个服务器不会执行查询,也就解决了上述超卖的问题。)

当然你用mysql事务也可以,但是分布式系统中,要共享的不一定是mysql又可能是其他存储介质(数据库)可能没有事务这个操作。

setnx -不存在就设置,存在就出错

解锁,del命令来完成

极端情况,某个服务器加锁成功,然后后续逻辑的过程中,程序崩了,没有解锁(JAVA中是为了保证解锁能够执行到,把解锁放到finally里面)->分布式系统中无效,进程内部才有效,又可以服务器掉电,无法执行finally,或者进程异常终止,这样的情况,导致redis设置的key,无人删除,导致其他服务器无法获取到这个锁

由此我们引入了过期时间,可以给set的keys设置过期时间的,一旦时间到,key就会被自动删除掉,set ex nx 比如设置key的过期时间为1000ms,意味着即使出现极端情况,某个服务器挂了,没有正确释放锁,这个锁最多保存1000ms,也就会自动释放了

setnx

expire这样分着设置可以吗? 注意⚠️这样设置不可以,redis无法保证原子性,不如一条命令稳妥

所谓的加锁:就是给redis上设置一个key-value

所谓的解锁,就是给redis上这个key-value删除掉

是否会出现,服务器1执行加锁,服务器2执行了解锁?

为了解决上述问题-引入校验机制

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

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

后续解锁的时候,就可以进行校验了,先查询一下这个锁对应的服务器编号,然后判定一下这个编号是否就是当前执行解锁的服务器编号,如果是,才真正执行del,如果不是就失败,服务器这边要完成的逻辑,通过上述校验,就可以有效避免误解锁,

在解锁的时候,先查询判定,再进行del->此处是两个操作,可能会出现问题,一个服务器内部,也可能是多线程的,可能同一个服务器,两个线程都在执行上述解锁操作(他是不针对某某,指定某某解锁,而是单纯的解锁,一定解开一个)。

实现中,更好的方案:lua脚本

lua是一个编程语言,作为redis内嵌的脚本,lua语言特别轻量,占用的体积小,可以使用lu a编写一定逻辑,把这个脚本上传到redis服务器上然后就可以让客户端来执行redis上述脚本了,(redis明确说明lua就是事务的替代方案)

过期时间的续约问题:加锁时候给key设置过期时间,那么设置多少合适呢?

时间短:业务逻辑没有执行完,就释放锁了,设置的不长,锁释放不及时的问题

更好的方式"动态续约"->往往也需要服务器有一个专门的线程,负责续约这个事情(看门狗🐶。广义的概念,很多场景都涉及这个狗)

初始情况,设置一个过期时间(如1s)就提前在还剩300ms的时候,如果当前任务还没执行完就再把时间续上1s,等到时间又快到了,任务还没执行完,就再续

如果服务器,中途崩了,自然没有人续约,此时锁就能较短时间被自动释放

使用redis作为分布式锁,那么redis本身有没有挂的可能呢?要想要保证高可用,就需要通过这样一系列的预案演习

集群->解决存储空间不足的问题

我们要随时考虑某个节点挂了的情况,需要保证某个节点挂,不会影响到大局

redlock算法(redis作者给的方案)

冗余

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狗哥不是甜妹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值