5

这是我的场景:

  • 我有两台服务器,每台服务器都有一个多线程消息队列消费者(总共两个消费者)。
  • 我有很多消息类型(CreateParent、CreateChild 等)
  • 我被糟糕的遗留代码所困扰(创建一个孩子将部分创建一个父母。我知道这很糟糕......但我无法改变它。)
  • 不能假设消息排序(消息排队原理!)
  • RabbitMQ 是我的消息队列代理。

我的问题:

  • 当两个线程同时运行时(一个执行 CreateParent,另一个执行 CreateChild),它们会产生冲突,因为这两个线程试图在数据库中创建 Parent(记住遗留代码!)

我最初的解决方案:

  • 在消费者内部,我创建了一个“实体锁定”概念。因此,例如,当线程处理 CreateChild 消息时,它会锁定 Child 和 Parent(遗留代码!!),以便 CreateParent 消息处理可以等待。我使用基本的 .net Monitor 和 Id 列表来实现这个概念。它运作良好。

我最初的解决方案限制:

  • 我的“实体锁定”概念适用于单个服务器上单个进程中的单个消费者。但它不适用于运行多个消费者的多个服务器。
  • 我正在考虑使用共享数据库来“存储”我的实体锁定概念,因此每个进程(和线程)都可以访问数据库以验证哪些实体被锁定。

我的问题(终于!):

所有这一切都变得非常复杂,它增加了错误风险和代码维护问题。我真的不喜欢!有没有人已经遇到过这种问题?他们是可接受的解决方法吗?有没有人对我的场景有一个干净的解决方案的想法?

谢谢!

4

1 回答 1

1

最后,简单的解决方案总是更好的解决方案!

我最终拒绝使用我的“实体锁定”概念的所有复杂性,而是在执行请求之前预先验证所有必需的数据和实体状态。

更准确地说,不是让 CreateChild 进程在遇到由 CreateParent 创建的现有数据时自行崩溃,而是在执行 CreateChild 消息之前完全验证数据库中的一切正常。

此解决方案的缺点是 CreateChild 的实现必须知道 CreateParent 将生成哪些特定数据并在开始执行之前验证它的存在。但是说真的,这比锁定所有东西在跨系统中要好得多!

于 2013-03-20T15:27:15.437 回答