`
huangyongxing310
  • 浏览: 508728 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

分布式锁的策略优缺点及对应处理

 
阅读更多
分布式锁的策略优缺点及对应处理



基于数据库
悲观锁—事务

将获取库存、判断有货、用户付款、扣减库存等多个数据库操作放到一个事务,,这样当一台机器与数据库建立链接请求了抢购商品这个事务,另外的机器只能等这个机器将请求完成才能操作数据库。

优点:是比较安全的一种实现方法。
缺点:在高并发的场景下开销是不能容忍的。容易出现数据库死锁等情况。



乐观锁—基于版本号
使用CAS, update table set surplus = aa where id = xx and version = y

失败重试,重试n次不成功,返回,

优点:乐观锁的性能高于悲观锁,并不容易出现死锁。
缺点:乐观锁只能对一张表的数据进行加锁,如果是需要对多张表的数据操作加分布式锁,基于版本号的乐观锁是办不到的。存在可能成功了,但返回失败



基于memcached
memcached的add指令是指如果有这个key,add命令则失败,如果没有这个key,则add命令成功。并且memcached支持设置过期时间的add原子操作。并发add同一个key也只有一个会成功。

定义一个key为分布式锁的key,如果add一个带过期时间的key成功则执行相应的业务操作,执行完判断锁是否过期,如果锁过期则不删除锁,如果锁没过期则删除锁。带过期时间是防止出现机器宕机,一直不能释放锁。

设想这样的执行序列:
1、机器A成功add一个带过期时间的key;
2、机器A在执行业务操作时出现较长时间的停顿,比如出现了较长时间的GC pause;
3、机器A还未在较长的停顿中恢复出来,锁已经过期,机器B成功add一个带过期时间的锁;
4、此时机器A从较长的停顿中恢复出来,执行完相应业务操作,删除了机器Badd的锁;
5、此时机器B的业务操作是在没有锁保护的情况下执行的。

注:过期时间一定要长于业务操作的执行时间。
优点:性能高于基于数据库的实现方式。


基于redis
redis提供了setNx原子操作。基于redis的分布式锁也是基于这个操作实现的,setNx是指如果有这个key就set失败,如果没有这个key则set成功,但是setNx不能设置超时时间。

基于redis组成的分布式锁解决方案为:
1、setNx一个锁key,相应的value为当前时间加上过期时间的时钟;
2、如果setNx成功,或者当前时钟大于此时key对应的时钟则加锁成功,否则加锁失败退出;
3、加锁成功执行相应的业务操作(处理共享数据源);
4、释放锁时判断当前时钟是否小于锁key的value,如果当前时钟小于锁key对应的value则执行删除锁key的操作。

注:这对于单点的redis能很好地实现分布式锁,如果redis集群,会出现master宕机的情况。如果master宕机,此时锁key还没有同步到slave节点上,会出现机器B从新的master上获取到了一个重复的锁。


基于zookeeper
1、客户端尝试创建ephemeral类型的znode节点/lock;
2、如果客户端创建成功则加锁成功,可以执行访问共享数据源的操作,如果客户端创建失败,则证明有别的客户端加锁成功,此次加锁失败;
3、如果加锁成功当客户端执行完访问共享数据源的操作,则删除znode节点/lock。

基于zookeeper实现分布式锁不需要设置过期时间,因为ephemeral类型的节点,当客户端与zookeeper创建的session在一定时间(session的过期时间内)没有收到心跳,则认为session过期,会删除客户端创建的所有ephemeral节点。

但是这样会出现两个机器共同持有锁的情况。设想以下执行序列。
1、机器A创建了znode节点/lock;
2、机器A执行相应操作,进入了较长时间的GC pause;
3、机器A与zookeeper的session过期,相应的/lock节点被删除;
4、机器B创建了znode节点/lock;
5、机器A从较长的停顿中恢复;
6、此时机器A与机器B都认为自己获得了锁。













https://blog.csdn.net/qq_35666577/article/details/80431019(几种常见的分布式锁的策略优缺点及对应处理)

















分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics