[锁机制] 分布式锁,redis和zookeeper的实现

1.分布式锁

现在的系统都是微服务模型,即各种组件单独运行在逻辑独立的机器中,之间通过rpc等方式调用并完成服务。

也因此数据的保存和数据的计算往往不在同一个地方,需要一个分布式框架的“全局锁”。其余所有系统都需要通过它获取锁。

实现分布式锁功能的,可以是redis这样的缓存数据库,也可以是MySQL这样的关系数据库,也可以是Zookeeper这样的分布式协调服务。

2.redis实现分布式锁

思路是在redis中专门使用一个string类型变量保存对应资源是否锁定。

1)访问资源前,通过setNX(set not exist)尝试获取锁,如果key为空则成功返回1,否则返回0。

命令类似于:

SET Lock TimeStamp NX

其中 Lock 为对应资源的key, TimeStamp为当前时间戳。

2)若setNX返回0,说明获取锁失败。考虑到可能有其他服务获取锁导致死锁的情况,可以获取Lock对应的TimeStamp值,检查时间戳是否过期(即资源已被占用超过一定时间)。如果超过时间则进行解锁,更新时间戳,否则需要等待锁释放。

3)释放锁

删除redis中的Lock值就行了。即 DELETE命令。

4)另外一种情况:不保存timstamp值,而是使用PX millionseconds参数来指定有效时间,到时会自动过期。

3.zookeeper实现分布式锁

zookeeper中基本的操作时创建和删除节点,节点为树状结构。

有序节点:创建后zookeeper会自动添加节点号,例如创建 lock-resource- ,那么zookeeper可能创建lock-resource-0000000001。

使用zookeeper的临时有序节点。获取锁即在zookeeper创建一个临时有序的节点。为了便于管理,将节点创建在保存Lock的父节点下。

临时节点:客户端会话结束或者超时后,zookeeper会自动删除该节点。

创建成功后,需要判断当前线程持有的节点是否是序号最小的节点。若是序号最小,则获取锁成功。

否则对当前节点序号的前一个节点添加一个事件监听,如果节点删除(锁释放了),则自己是最小的节点,那么获取到锁。

4.比较

redis:

1)需要反复尝试获取锁,消耗性能。

2)redis可能会有健壮性问题。

zookeeper:

1)天然支持分布式,健壮性强。

2)不需要反复尝试获取锁,可以添加监听器。

posted @ 2022-02-23 16:36  Cheung-10  阅读(2)  评论(0)    收藏  举报