分布式锁

分布式锁一般来说有三种实现方式,分别基于:数据库、redis、zookeeper

数据库

  • 可以利用关系数据库的唯一键实现,例如各个不同节点拿着相同的业务key插入键字段,插入成功则获得锁
  • 利用数据库表乐观锁,常用方法就是增加一个版本标识
  • 利用数据库表悲观锁(排它锁),如mysql中使用:select * from MethodLock where methodName = 'xxxx' for update;

redis

  • 利用redis命令(不存在就插入):setnx key value,所有节点的key都相同,value随便写什么,1代表成功拿到锁,0代表失败
  • 释放锁就是删除key命令:del key
    存在的问题:节点获得锁之后,宕机了,导致锁得不到释放,就形成了死锁
    解决办法
  1. 设置key过期:expire key timeout,相当于把锁持有的有效期交给redis控制
  2. 把删除key的权利交给其他服务器,这时value中就需要有一个过期时间字段:expiretime,如果服务器2发现expiretime已经超过阈值,则删除key,再执行setnx命令获得锁;
    但是这里又有另外一个问题,就是在服务器2删除key,执行setnx命令后,如果服务器3紧接着删除key并执行setnx,这时服务器2和服务器3都拿到锁了;可以用命令(获取旧值,设置新值):getset key value;
    意思是如果服务器2发现key过期了,调用getset命令,获取expiretime字段后判断是否过期,过期了则拿到锁,否则可能是服务器3先执行了getset操作拿到了锁,这里其实有个小问题,就是服务器3修改了有效期拿到了锁后,服务器2也修改了有效期,但没拿到锁,相当于有效期多了一倍,但是这种影响一般很小

zookeeper

未完

原文地址:https://www.cnblogs.com/yinchh/p/10520248.html