分布式锁原理介绍

分布式服务中,如果各个服务节点需要竞争资源,不能像单机多线程应用一样使用线程锁,需要由一套分布式锁机制保证节点对资源的访问。通常分布式锁以单独的服务方式实现,目前比较常用的分布式锁实现有三种:zookeeper实现、redis实现和memcache实现。后两者本质上相同。

一个需要用到分布式锁的典型场景是,分布式服务的各个节点注册到用于服务发现的服务器,注册后的节点需要是有序的。此时就需要有锁来保证各个节点按先后顺序注册。

下面分别介绍三种实现方式的原理。

一、zookeeper
1、实现原理
基于zookeeper临时顺序节点实现分布式锁,其大致思想为:
(a)每个客户端对某个功能加锁时,在zookeeper上的与该功能对应的指定节点的目录下,生成一个唯一的临时顺序节点;
(b)所有临时顺序节点中序号最小的,即为当前持有锁的节点;
(c)释放锁时,将自己注册的这个临时顺序节点删除即可。

以上实现方法,可以在客户端监听注册节点目录的变化,当发生节点删除时通知各个客户端检查是否自己持有了锁。
如果集群规模很大,这样做可能引起羊群效应,此时可以优化为客户端监听注册节点目录下,比自己节点小的节点变化。当比自己小的节点都删除了,那么自己就持有了锁。
--具体看 https://blog.csdn.net/xiaoliuliu2050/article/details/51226237

2、优点
锁安全性高,zookeeper数据不易丢失

3、缺点
性能开销比较高。因为其需要动态产生、删除临时顺序节点,还需要监听节点变化来实现锁功能。

4、开源实现
curator开源库中提供了分布式锁的实现,python库Kazoo中也可直接通过kazoo.recipe中的lock.Lock,调用acquire方法实现。
menagerie基于Zookeeper实现了java.util.concurrent包的一个分布式版本。

二、redis分布式锁
1、实现原理
利用redis中的set命令来实现分布式锁。
 
从 Redis 2.6.12 版本开始,set可以使用下列参数:
SET KEY VALUE [EX seconds] [PX milliseconds] [NX|XX]
 
  EX second :设置键的过期时间为 second 秒。 SET key value EX second 效果等同于 SETEX key second value 。
  PX millisecond :设置键的过期时间为 millisecond 毫秒。 SET key value PX millisecond 效果等同于 PSETEX key millisecond value 。
  NX :只在键不存在时,才对键进行设置操作。 SET key value NX 效果等同于 SETNX key value 。
  XX :只在键已经存在时,才对键进行设置操作。

返回值:
  SET 在设置操作成功完成时,才返回 OK 。
  如果设置了 NX 或者 XX ,但因为条件没达到而造成设置操作未执行,那么命令返回空批量回复(NULL Bulk Reply)。

命令:
> SET key value EX ttl NX

大致思想是:
(a)SET lock currentTime+expireTime EX 600 NX,使用set设置lock值,并设置过期时间为600秒,如果成功,则获取锁;
(b)获取锁后,如果该节点掉线,则到过期时间ock值自动失效;
(c)释放锁时,使用del删除lock键值;

使用redis单机来做分布式锁服务,可能会出现单点问题,导致服务可用性差,因此在服务稳定性要求高的场合,官方建议使用redis集群(例如5台,成功请求锁超过3台就认为获取锁),来实现redis分布式锁。详见RedLock。

2、优点
性能高,redis可持久化,也能保证数据不易丢失;
redis集群方式提高稳定性。

3、缺点
使用redis主从切换时可能丢失部分数据。

4、开源实现
python版本的开源实现:python-redis-lock。


三、memcached分布式锁
1、实现原理
利用memcached的add函数实现分布式锁。
add和set的区别在于:如果多线程并发set,则每个set都会成功,但最后存储的值以最后的set的线程为准。而add的话则相反,add会添加第一个到达的值,并返回true,后续的添加则都会返回false。利用该点即可很轻松地实现分布式锁。

2、优点
因为是全内存存储,并发高效。

3、缺点
(1)memcached采用列入LRU置换策略,所以如果内存不够,可能导致缓存中的锁信息丢失。
(2)memcached无法持久化,一旦重启,将导致信息丢失。

4、开源实现
待查。
 
 
 
参考
http://surlymo.iteye.com/blog/2082684
http://www.cnblogs.com/moonandstar08/p/5705619.html

zookeeper实现方式
http://graduter.iteye.com/blog/2024190
http://surlymo.iteye.com/blog/2082684
http://blog.csdn.net/xiaoliuliu2050/article/details/51226237

redis实现方式
https://redis.io/topics/distlock
http://blog.csdn.net/daiyudong2020/article/details/51760648
http://www.weizijun.cn/2016/03/17/聊一聊分布式锁的设计/
http://blog.csdn.net/u013970991/article/details/52722680

猜你喜欢

转载自www.cnblogs.com/aoyihuashao/p/9012632.html