redis实现分布式锁的几种方式 分布式锁的实现方式redis( 三 )


25、这个SDK提供的API非常友好,可以像操作本地锁一样操作分布式锁 。一旦客户端锁成功,就会启动一个watchdog看门狗线程,这个线程是一个后台线程,每隔一段时间就会检查一次(这个时间的长短和设置锁的到期时间有关) 。如果客户端在检查的时候仍然持有锁密钥(也就是说,它仍然在操作共享资源),那么它将延长锁密钥的生存期 。
26、锁成功锁定后客户端宕机怎么办?停机后,看门狗任务将不存在,并且锁不能被更新 。锁到期后会自动失效 。Redis部署模式对锁的影响上述情况都是Redis单个实例可能出现的问题,不涉及Redis的部署架构细节 。
27、到目前为止,Redis的几种常见部署架构有:单机模式;主从模式;哨兵(sentinel)模式;集群模式;我们在使用redis时,通常采用主从集群+哨兵的模式,哨兵的作用是监控Redis节点的运行状态 。普通主从模式,当主崩溃时,需要手动切换从成为主 。采用主从和哨兵相结合的方式,好处是当主设备非正常宕机时,哨兵可以实现自动故障切换,将从设备升级为新的主设备并继续提供服务,从而保证可用性 。
28、那么,当主从切换时,分布式锁还安全吗?想象这样一个场景:客户端1在master上执行SET命令,加锁成功此时,master异常宕机,SET命令还未同步到slave上(主从复制是异步的)哨兵将slave提升为新的master,但这个锁在新的master上丢失了,导致客户端2来加锁成功了,两个客户端共同操作共享资源可以看出,当引入Redis副本时,分布式锁仍然可能受到影响 。即使Redis通过sentinel高度可用,如果主节点由于某种原因从主节点切换到从节点,锁也会丢失 。集群模式+红锁实现高可靠分布式锁为了避免Redis实例失效导致的锁失效,Redis的开发者Antirez提出了分布式锁算法Redlock 。
29、Redlock算法的基本思想是让客户端和多个独立的Redis实例依次请求锁定 。如果客户端能够成功完成半数以上实例的加锁操作,那么我们认为客户端已经成功获得了分布式锁,否则加锁失败 。这样,即使单个Redis实例失败,由于锁变量保存在其他实例中,客户端仍然可以正常锁,锁变量不会丢失 。
30、我们来具体看一下红锁算法的执行步骤 。Redlock算法的实现需要Redis采用集群部署模式,不需要哨兵节点,需要n个独立的Redis实例(官方推荐至少5个实例) 。接下来,我们可以分3步完成锁定操作 。
31、之一步是客户端获取当前时间 。第二步,客户端依次对N个Redis实例执行锁定操作 。这里的锁定操作与在单个实例上执行的操作相同,使用SET命令、NX、EX/PX选项以及客户机的唯一标识 。
32、当然,如果Redis实例失败,为了保证这种情况下Redlock算法能够继续运行,我们需要为锁定操作设置一个超时 。如果客户机在超时之前没有请求锁定Redis实例,那么客户机将继续请求锁定下一个Redis实例 。锁定操作的超时需要远小于锁的有效时间,通常设置为几十毫秒 。
33、第三步是,一旦客户机完成了对所有Redis实例的锁定操作,客户机将计算整个锁定过程的总时间 。只有当客户端满足两个条件时,才可以认为锁被成功锁定 。之一个条件是客户端已经成功地从超过一半(N/2+1)个Redis实例中获取了锁;第二个条件是客户端获取锁的总时间不超过锁的有效时间 。
34、为什么大多数实例成功锁定才算成功?当多个Redis实例一起使用时,它们实际上形成了一个分布式系统 。分布式系统中总会有异常节点,所以在谈分布式系统时,需要考虑有多少个异常节点,仍然不会影响整个系统的正确运行 。这是一个分布式系统的容错问题 。
35、这个问题的结论是,如果只有故障节点,只要大部分节点正常,整个系统仍然可以提供正确的服务 。满足这两个条件后,我们需要重新计算这个锁的有效时间,计算的结果是锁的初始有效时间减去客户端获取锁所花费的总时间 。如果锁的有效时间来不及完成共享数据的操作,我们可以释放锁,避免在共享资源的操作完成之前锁就过期的情况 。

推荐阅读