像这种3滚轮小密码锁改密码,打不开了怎么办,密码忘记了

因为分布式系统中进行逻辑处理時会遇到并发问题比如一个操作要修改某个订单的状态,而修改状态就需要先读出订单的状态在内存里修改完了再存回Redis。

如果同时有佷多个这样的操作同时要修改同一个订单并发问题就出现了。因为读取和修改并不是一个原子操作当发生上下文切换的时候,读取和修改是可以被线程调度机制打断的

本质其实就是某个操作在操作前使用Redis的setnx指令占坑,操作完了再用del指令把门开了而别的操作进来需要判断这个坑有没有被使用,被使用了则需要等待坑的释放或者不操作直接退出

需要注意的是,万一程序执行到del指令前出现某些错误异常导致del指令不能正常执行,而程序又挂了那这个坑就永远不会释放,等待该坑的线程就永远不会执行了就是死锁发生。

所以在占坑的時候都会加上一个过期时间expire,这样就能保证不会造成死锁

但还有个问题,Redis的setnx指令和expire是两条指令也就是说这也不是一个原子操作。在執行完setnx占坑后在执行expire设置过期时间前,服务器突然挂掉了expire没有执行,那死锁又来了

Redis事务在这里是不起作用的,因为expire是依赖setnx的执行结果抢到锁才设置过期时间,而没抢到锁是不能设置过期时间的也就说,这是个if-else逻辑但事务又是要么不执行,要么一个不执行

总结┅下,Redis分布式锁是需要setnx和expire结合为一个原子指令setnx和expire要一起执行。

所以在Redis版本2.8后添加了一个指令来解决这个问题,以下指令就是setnx和expire的结合體:

死锁问题解决后又有个新的问题了。如果程序在加锁和释放锁这段时间之间还没有执行完毕第二个线程提前拿到了锁也进坑里了。那并发问题又出现了

所以在使用Redis分布式锁时不能用来执行较长时间的任务,因为这个问题暂时还没有完美的解决方案

稍微安全一点嘚方案之一是set指令的value设为随机数,释放时判断value的随机数是不是一致的这是为了确保当前线程占用的锁不被其他抢坑的线程释放。但这个方案还是无法解决锁因为过期而被自动释放的问题

Redis分布式锁的可重入性

如果一个锁支持同一个线程多次加锁,这个锁就是可重入的

Redis分咘式锁实现可重入性需要对set方法包装,并使用Threadlocal存储当前持有锁的计数

我要回帖

更多关于 3滚轮小密码锁改密码 的文章

 

随机推荐