详细了解Redis分布式锁

342 阅读3分钟

之前有一个简单的redis实验,请看Redis分布式锁

这里主要详细了解redis分布锁的常见问题:

  • Q1:为什么redis分布式锁能解决多台机器访问共享变量出现脏数据的问题

    A1:我们使用setnx ex来对一个key加锁,setnx ex原子操作的请求都会到redis服务上,而因为redis是单线程处理所有的任务,所以到redis所有的任务都会排队执行,所以不会出现多个请求同时对某个锁进行操作的场景。

  • Q2:若拿到锁的进程业务出现故障,就出现锁资源不会被释放、死锁的情况,这种情况该怎么解决?

    A2:对某一个任务拿到锁后,对这个锁加一个超时时间。超过该时间,这个锁无效,这样其他进程拿到锁可以正常执行业务。

    eg:set product:100001 true ex 10 nx key商品100001设置锁的超时时间为10s,超过10s,该锁自动无效。注意这里setnx ex 是原子操作,要么同时执行成功,要么同时执行失败。

  • Q3:超时时间设置太短,以至于业务A没有执行完锁失效,业务B开始加锁,执行B业务。A到时间恢复业务因为还没有释放锁,这个时候会释放了B的锁。会给B业务造成影响,严重也会出现锁失效的问题。

    A3:每一个进程生成一个自己的UUID,释放锁的时候判断当前线程是否是自己ID。若是自己进程的锁才会进行释放。当然这里判断与释放,应该要保证是原子语句,否则会出现当判断完线程是自己ID,但在释放锁之前,锁失效

    当然有最简单的方法:根据具体业务设置对应的超时时间,设置较长的超时时间,也会规避该问题。这样成本低一点

  • Q4:超时时间设置的问题,设置多大才算是OK的

    A4:有时我们不清楚业务执行时间是多大,所以不确定最合适的超时时间。可以有最优的方法是:在业务主进程行开始时(设置超时时间是30s),加一个监听协程,定时(10s)监听主业务是否执行完,若没有执行完,则继续设置超时时间为30s。这就是锁续命的问题。定时监听常设置1/3的初始超时时间。

  • Q5:redis分布式锁在主从架构中,切换主节点期间也可能出现锁失效的问题。怎么解决?

    A5:在主节点切换的时候,有可能没有把原主节点还未释放的锁复制到新主节点上,那另一个进行可以在新主节点继续申请该锁,出现业务紊乱的问题。

    分布式的原则是CAP:一致性,可用性和分区容错性。Redis实现主要是AP原则,更注重可用性。而zookeeper实现主要是CA原则,更注重一致性。

    所以解决这个问题,可以使用zookeeper分布式锁。zookeeper 数据存储是树型结构,有多个节点的时候,将节点的角色分为Leader和fllower,leader每收到一个key信息,都会复制(同步)到flower节点上(超过一半的节点),然后再把成功信息返回到客户端。这样主节点切换的时候,因为新节点会在数据最多的flower节点上进行选择,而数据最多的flower节点也一定会包含原主节点所有的key信息。

    当然,难道redis就不能解决这个问题吗?可以的。

    使用redlock算法。redlock原理:发送加锁请求的时候,会给每一个节点发加锁请求,超过半数redis节点加锁成功才算加锁成功。