面试官:Zookeeper 怎么实现分布式锁?和 Redis 分布式锁的区别?

前言:Zookeeper 是一个开源的分布式协调服务,可以用于实现分布式锁。本文将介绍如何使用 Zookeeper 实现分布式锁。

简介

  • 本地锁:比如在单机服务A JVM 上使用 Synchronized 关键字来对一个共享资源上锁,但是这个 Synchronized 只能保证这台机器的锁,如果是集群模式,服务A也在另一台机器上运行呢?就无法保证同一时间只有一个线程访问到共享资源了。
  • 分布式锁:在分布式系统中,为了保证数据的一致性和安全性,需要使用分布式锁来协调各个节点的访问。

Zookeeper 实现分布式锁

Zookeeper 实现分布式锁有两种方式,一种是排他锁(X锁),一种是共享锁(S锁)。

排他锁实现

排他锁 Exclusive Locks,简称 X 锁,又称写锁/独占锁,如果事务 A 对某个对象加了排他锁,其他事务则不可对该对象增加 X 锁或者 S 锁,直到事务 A 释放了该锁。

  1. 在 Zookeeper 中,先创建一个节点,假设是 /exclusive_lock,然后多个客户端就可以在这个节点下创建一个规定命名的临时节点,假设是 lock,所有客户端只有一个客户端能创建成功,创建成功即获得锁。
  1. 同时,没有获得锁的客户端就在 /exclusive_lock 上注册一个子节点变更的 Watcher 监听,以便实时监听 lock 节点被释放(删除)的情况。
  2. 一般来说会有两种情况:一是客户端正常执行完逻辑后,删除节点 lock。二是客户端宕机了,因为 lock 是临时节点,也会被删除。无论如何锁都会被释放,Zookeeper 就会通知所有在 /exclusive_lock 注册监听的客户端,他们收到通知后,就可以重新开始对锁进行抢占,从步骤 1 开始。
共享锁实现

共享锁 Shared Lock,简称 S 锁,又称读锁。根据操作系统基本知识,如果一个对象上有 S 锁,那其他事务可以继续加 S 锁,但不能加 X 锁。并发性比较好。

  1. 和排他锁一样,先创建一个节点,假设是 /shared_lock,然后我们为了方便,在锁节点名称上就能看出是哪个客户端,是 X 锁还是 S 锁,我们将锁节点的命名设置为host-W/R-序号 的形式,这里可以看出是想创建一个顺序节点,为什么要加上序号呢?为了方便我们判断 W 锁和 S 锁的顺序,往下看就知道了。
  2. 所有客户端根据自身需要,到 /shared_lock 节点下创建临时顺序节点,如:
  1. 创建完节点后,需要通过 Zookeeper 来判断读写顺序:

    • (1)客户端创建完节点,获取 /shared_lock 节点下是所有子节点,并对 /shared_lock 的变更注册监听。
    • (2)确定自己的节点的顺序
      • 对于读请求,如果比自己小的节点都是读节点,可以直接读。如果比自己小的有写节点,不可读。
      • 对于写请求,若自己不是序号最小的节点,则等待。
    • (3)接受 Watcher 事件通知,重复(1)的步骤。
  2. 释放锁,和排他锁的释放流程一样。

羊群效应

上面虽然可以实现共享锁的功能,但是仔细想想,有没有问题?

机智的同学可能想到了,监听通知事件有许多个客户端做了无用功。假设现在的客户端情况如下:

可以看到,在 host1 移除之后,其他所有客户端都会收到通知事件,但其实有影响的只是 host2,能进行加 X 锁写操作。其他的客户端被唤醒后还是要继续等待监听。这就是所谓的羊群效应

羊群效应会给 Zookeeper 服务器造成巨大的性能影响和网络开销!!!

那上面的共享锁有什么改进办法吗?有,更改几个关键步骤:

  1. 客户端创建节点后不要在父节点上注册监听了。
  2. 对于读请求,向比自己序号小的最后一个 W 节点注册 Watcher 监听(exist监听)。
  3. 对于写请求,向比自己序号小的最后一个节点,无论 R 节点还是 W 节点,注册 Watcher 监听(exist监听)。

这样更改就可以避免羊群效应了(不会通知全部客户端了)。

Zookeeper 和 Redis 分布式锁的区别及应用场景

  1. 性能不同
    • Redis 分布式锁是直接用 key 去 set value,内存中,速度快,性能好。
    • Zookeeper 需要在一个目录结构树下创建一个节点。性能不好。
  2. 锁的释放时机不同
    • Reids 分布式锁释放时机:1 执行完成,2 超时释放。
    • Zookeeper 分布式锁释放时机:1 执行完成,2 客户端宕机。
  3. 使用场景不同
    • Redis 适合单机,使用简单方便,使用 Redis 集群有可能在主节点获取锁后宕机,又没同步到子节点。
    • 如果需要集群的分布式锁则使用 Zookeeper,可以保证强一致性。

总的来说,Zookeeper 分布式锁适合集群,适合需要强一致性的环境。

相关推荐
坐吃山猪1 天前
zk02-知识演进
运维·zookeeper·debian
yumgpkpm1 天前
华为鲲鹏 Aarch64 环境下多 Oracle 数据库汇聚操作指南 CMP(类 Cloudera CDP 7.3)
大数据·hive·hadoop·elasticsearch·zookeeper·big data·cloudera
小醉你真好2 天前
16、Docker Compose 安装Kafka(含Zookeeper)
docker·zookeeper·kafka
yumgpkpm3 天前
CMP (类ClouderaCDP7.3(404次编译) )华为鲲鹏Aarch64(ARM)信创环境多个mysql数据库汇聚的操作指南
大数据·hive·hadoop·zookeeper·big data·cloudera
yumgpkpm6 天前
大数据综合管理平台(CMP)(类Cloudera CDP7.3)有哪些核心功能?
hive·hadoop·elasticsearch·zookeeper·big data
回家路上绕了弯9 天前
深入 Zookeeper 数据模型:树形 ZNode 结构的设计与实践
后端·zookeeper
9091932219 天前
SQL关键词标签在数据分析中的应用与实践
zookeeper
小马爱打代码9 天前
zookeeper:一致性原理和算法
分布式·zookeeper·云原生
小马爱打代码10 天前
zookeeper:架构原理和使用场景
分布式·zookeeper·架构
thginWalker10 天前
ZooKeeper源码分析与实战-模块五:原理篇
zookeeper