【问题标题】:Distributed locks in Microservice architecture微服务架构中的分布式锁
【发布时间】:2020-02-05 14:06:37
【问题描述】:

我们有一个架构设置,其中客户端应用程序在服务器中运行,我们希望有一个微服务负责提供分布式锁/映射/缓存功能。该微服务内部使用 Redisson,这是一个基于 Java 的客户端,可以与 Redis 通信。现在我们想提供客户端应用程序可以使用的微服务的 api 锁定、解锁、获取、放置。对于应用程序到微服务的通信,我们将使用 gRPC 协议。

从微服务向客户端提供锁定/解锁 API 的正确方法是什么? 目前,我们使用基于 RedissonMap RMap.getLock(..)) 的 Redisson 的 Semap,它遵循 java Lock 规范,因此获取分布式锁的线程只能解锁。一个问题是由于锁定是由微服务处理的,因此客户端必须发出单独的锁定和解锁请求,这些请求可能由同一节点(微服务)和同一线程提供服务,也可能不提供。这可以通过使用信号量(有 1 个许可证)来解决。所以,本质上我们使用redisson的Rsemaphore来服务互斥的用例

我更感兴趣的是找出当我们提出获取/释放的 API 规范时需要考虑的因素,例如在微服务上对获取/释放许可的调用应该是同步的还是异步的。

【问题讨论】:

  • 我质疑您为什么要“拥有一个负责提供分布式锁/映射/缓存功能的微服务”。您可以部署预先存在的协调服务,这些服务已经可以为您提供此类功能,例如 ZooKeeper 或 etcd。至于“异步与同步”,如果您使用 gRPC,则在 API 级别无关紧要,因为 gRPC 支持两者,客户端可以使用他们想要的任何一个。
  • 当我说从微服务提供锁定功能时,我并没有重新发明任何新东西。这只是为了摆脱核心应用程序中的 3rd 方服务依赖关系。关于同步与异步,我担心的是让获取/锁定 api 同步是一个好习惯,因为它可能会在高并发下保持连接更长时间。这是否偏离微服务的标准实践

标签: multithreading microservices semaphore redisson distributed-lock


【解决方案1】:

我有一个类似的问题——在某些时候——除非它是“轮询”,否则只有微服务必须阻止客户端等待信号量完成。 如果阻塞是不可接受的,则不需要信号量。 即使每次调用来自不同的 JVM(可能是从该 JVM 到 redis 的初始连接),以下逻辑也应该可以正常工作—— 仅临时使用其中一个 RLock 对象或 Atomic - 足够长的时间来更新具有某些唯一 ID(由客户端或微服务提供)的键或映射条目。 然后将其“安全地”存储在 Redis 中,并表示类似“锁”之类的东西。 如果你在密钥上使用过期时间,那么这会给你一个“锁”上的 TTL。

如果您的应用可以在等待信号量释放时阻塞微服务,那么来自不同微服务的调用应该可以正常工作。这与您有 2 个长期运行的 JVM 直接连接到 redis/redisson 但每个只使用一次信号量的模型相同。

您不能(轻松地)做的是在您返回客户端时仍然“持有”“锁” 然后稍后调用(不同的 JVM)微服务来释放锁。

【讨论】:

    【解决方案2】:

    比如微服务上获取/释放许可的调用应该是同步的还是异步的

    这取决于信号量强制执行的逻辑。仅对在获取/释放块内执行的异步逻辑使用异步方式。

    【讨论】:

      猜你喜欢
      • 2019-04-14
      • 2021-04-21
      • 2019-01-02
      • 2018-08-13
      • 2015-12-26
      • 2021-11-02
      • 2017-03-19
      相关资源
      最近更新 更多