【问题标题】:Efficient exclusive lock with ZooKeeper for infrequent operations使用 ZooKeeper 的高效排他锁,用于不频繁的操作
【发布时间】:2020-01-27 18:05:54
【问题描述】:

我在多个服务器上部署了一个微服务,它有两个主要的数据源:

  1. 以高容量(100-1000 事件/秒)持续 (24/7/365) 接收事件

  2. 一天一次的操作,可能需要一点时间才能完成

我想以独占模式运行这个一天一次的处理:暂停事件处理,运行一天一次的任务,然后恢复事件处理。我已经有办法正确启动一天一次的操作,但我仍然必须在 1 和 2 之间实现锁定以确保排他性。

我发现的大多数 ZooKeeper 配方都需要对每个已处理的事件进行写入操作,例如使用InterProcessReadWriteLock 读取锁定获取或使用DistributedAtomicLong 增加计数器。由于每天一次的操作很少发生,因此每个事件的开销似乎很浪费。

是否有针对此类用例优化的 ZooKeeper/Curator 收据?

我考虑过,但我不能 100% 确定这是否是正确的方法(以及如何实施下面的第 2 点):

  1. 当一天一次的操作开始时,在 ZooKeeper 中创建新的 /exclusive 路径
  2. 等待所有机上活动完成
  3. 在处理事件之前检查/exclusive 是否存在。如果它在那里停止处理,直到 /exclusive 路径被删除
  4. 当一天一次结束时,删除/exclusive 路径

【问题讨论】:

    标签: java apache-zookeeper apache-curator


    【解决方案1】:

    这个怎么样?

    每个事件处理器必须:

    • 通过InterProcessReadWriteLock获得读取锁。
    • 使用NodeCache 观察“信号”节点并监听该节点上的变化。当节点存在时,意味着它是每日处理时间。当它不存在时,事件处理可以继续。
    • 当 NodeCache 显示信号节点已创建时,事件处理器必须释放它们的锁并等待信号节点被删除(再次通过侦听 NodeCache)。
    • 当 NodeCache 显示信号节点已被删除时,事件处理器再次获取读锁并继续处理事件。

    一旦设置好,ZooKeeper 就不会再运行其他活动了。

    当一天一次的操作准备好运行时:

    • 它创建信号节点(作为临时节点)
    • 在与事件处理器用于其读锁的路径相同的路径上获取
    • 是否定期处理
    • 释放写锁
    • 删除信号节点

    但是,这有一个很大的警告,这就是 JVM 暂停可能发生的情况。另请阅读Tech Note 了解重要的边缘情况。

    【讨论】:

    • InterProcessReadWriteLock获取读锁不是ZooKeeper中的写操作(创建路径)吗?
    • 是的——但你只做一次。每个事件处理器在启动时都会获得一次读锁。我假设事件处理器是长时间运行的实例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多