分布式锁实现方式
分布式锁的概念在这里我们不展开详述,在市面上常规的实现方式大概有3种:Mysql、redis、zookeeper,其中Mysql数据库实现方式不会再项目中实战使用,效率低且没有完善的组件配合,需要自己写一套补偿代码。ZooKeeper中采取的是CP模式实现,对于可靠性要求不高的业务才会选择此项实现,这里我们也不展开细说。今天我们主要讲的是redis的实现方式以及其中机制细节。
Redis如何实现分布式锁
Redis中实现分布式锁主要是以下步骤:
1、每一个分布式锁有独特的数据标识,检查数据标志是否已经存在。
2、如果没有数据存在则插入数据。
3、释放锁也就是将数据从Redis中删除。
因为是并发场景所以需要将1、2两步操作一起实现,不可切割,Redis中有SETNX命令,这一命令带有原子性,可以满足要求。
Redis数据弱一致性问题
在介绍分布式锁实现的时候,提到了ZooKeeper采取的是CP模式实现,实现了数据强一致性,在Redis中实现的是AP模式,也就是放弃了数据的强一致性,选择了高可用和分区容错。那么我们分布式服务肯定需要保证数据的一致性才能使用,在Redis中有一个机制保证分布式锁能够保证一致性。
Redis中红锁机制
多数派原则
与红锁机制绑定的概念是多数派原则,这一原则在分布式系统中并不少见,在之前学到的Raft和Paxos分布式一致性算法中就运用了这一原则作为基础展开,具体概念是,需要保证半数以上的节点能够完成命令才能执行命令,否则就无法执行命令。
红锁实现原理
在Redis中,我们请求加锁,这时候客户端就会向所有节点发送加锁请求,因为弱一致性可能导致在其他服务器本地已经被人占用锁,直到半数以上的节点加锁成功,才能算执行命令成功,如果加锁失败,就会遍历所有节点发送解锁请求。这样就解决分布式锁的数据弱一致性的问题。
Redis中分布式锁因过期导致的问题
Redis中在插入数据时会带有过期时间的设置,这也带来了分布式服务出现过期时间不确定的问题,这会导致锁的独占性被破坏,也就是多个服务同时持有一把锁。所以为了避免这种情况,Redis的实现组件Redisson中提出了看门狗策略。
看门狗策略
因为上述的过期时间不确定的问题,Redisson中采取了延迟任务协程的机制来让过期时间不断延后,在执行完线程之后,守护线程也会被销毁,就会停止延长过期时间,过一定时间就会释放分布式锁。在看门狗机制中,默认由每10S就由守护线程执行延长至当前30S后过期锁,在持有锁的线程销毁后,协程也会结束,也就是在30S后就会释放分布式锁。