面试官: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 分布式锁适合集群,适合需要强一致性的环境。

相关推荐
可儿·四系桜16 小时前
如何在多台Linux虚拟机上安装和配置Zookeeper集群
linux·服务器·zookeeper
Lill_bin1 天前
深入理解ElasticSearch集群:架构、高可用性与数据一致性
大数据·分布式·elasticsearch·搜索引擎·zookeeper·架构·全文检索
xcx0032 天前
快充协议方案,Type-C接口受电端Sink取电快充协议芯片
zookeeper·rabbitmq·flume·memcached·storm
QDNBD2 天前
【zookeeper安装】zookeeper安装详细教程(单机/集群部署)(linux版)
linux·zookeeper
二进制杯莫停2 天前
初识zookeeper
分布式·zookeeper·云原生
赵渝强老师2 天前
【赵渝强老师】基于ZooKeeper实现Hadoop HA
大数据·hadoop·分布式·zookeeper
兮动人3 天前
错误: 找不到或无法加载主类 org.apache.zookeeper.server.quorum.QuorumPeerMain
分布式·zookeeper·apache
星辰@Sea3 天前
ZooKeeper远程连接超时排查与解决
linux·分布式·zookeeper
Lill_bin3 天前
ElasticSearch底层原理解析
大数据·分布式·elasticsearch·搜索引擎·zookeeper·云原生·jenkins
编程经验分享4 天前
Windows 安装 ZooKeeper 以及 IDEA 安装 zoolytic 连接工具
分布式·zookeeper·云原生