architecture - 消息需要访问共享数据时的消息队列架构

标签 architecture message-queue motion-detection

我必须建立一个运动检测服务。运动检测不适用于视频,而仅适用于静止图像。

该微服务需要能够无序接收图像(带有时间戳)和 找出图像是否与之前拍摄的图像不同 (时间戳早于它)。将需要多个运动检测工作人员。

因此,关键要求似乎是:

  • 一个不按顺序接收图像的 Web 服务能够将它们分为前一对和后对,然后计算图像与其前一图像相比是否有运动。
  • 许多图像制作者 - 整个过程似乎平均每秒大约 100 张图像
  • 众多运动检测消费者
  • 优先考虑延迟而不是吞吐量。
  • 不容易独立消耗的任务。

  • 我正在考虑使用单个消息队列。生产者将图像文档推送到队列中。然后运动检测工作人员从此队列中读取数据,并向该文档添加“diff_percentage”字段,并更新数据库中的该记录。

    给定队列中的任务,工作人员可以单独操作该任务,方法是直接从数据库中获取之前的图像并进行比较,然后更新数据库中的记录。不幸的是,虽然这足够好,但它会非常慢。我想我需要减少从数据库中读取。理想情况下,我希望这个“队列”能够缓冲,直到它具有给定作业所需的图像。就像......当一个工作人员从队列中读取时,检查它需要比较的图像是否在队列中,如果没有,转到数据库。

    任何人都可以指出我正确的方向吗?也许队列不是我想要的?也许是一个队列和某种缓存桶?

    最佳答案

    具有多个生产者和多个消费者的图像队列在这里似乎是正确的方法。对于这个答案的其余部分,我将从这个队列的细节中抽象出来,因为这些细节取决于生产者和消费者的位置(物理上在哪台机器上)。

    以下是在消费者端要做的事情:

    暂时保留图片在内存中 hash table .键是时间戳,值是指向图像内容(以及您可能想要保留的任何元数据)的指针。一旦将图像与连续时间戳的图像进行比较,就可以将图像从哈希表中删除。

    您的消费机器需要有足够的工作内存来存储图像。如果在给定的时间戳与其之前或之后的时间戳之间平均收到 100 张图像,并且图像的平均大小为 1MB,则这些图像总共将占用 100 * 2 * 1MB = 200MB 的内存。

    创建第二个内存队列以跟踪尚无法比较的图像。如果在接收具有当前时间戳的图像时无法从哈希表中获得具有上一个时间戳的图像,则工作人员会将带有时间戳的图像指针放入该队列。第二组工作人员从这个队列中获取时间戳,并测试前一个时间戳的图像是否同时可用。如果是,则比较图像,否则将图像和时间戳推回到队列中。

    第一组和第二组工作人员的相对大小应与其直接后继人员之前到达的图像的相对频率成正比。换句话说,如果图像有 60% 的时间在其直接后继者之前进入哈希表(因此图像在其直接后继者之后到达的时间为 40%),则 60% 的工作人员应该在第一组中,而 40%应该在第二组。或者,您可以根据需求动态地将工作人员分配给一个集合;如果无序行为往往波动很大,例如取决于一天中的时间,这可能是合适的。

    具有单个消费者的第三个队列负责更新数据库。第三个队列可能跨网络也可能不跨网络,就像第一个队列一样。在前两组中的工作人员比较了两个连续的图像后,它将结果推送到第三个队列中。这个队列的消费者获取队列的内容并将它们同步到数据库。它可以通过每几个(比如 10 个)比较的一个事务来实现这一点,以最大限度地减少延迟,或者每秒将所有内容集中在一个事务中,以最大限度地提高吞吐量。不要为每个图像比较单独创建事务,这可能会比您想要的慢得多。

    图像比较 worker 都需要读取和更新哈希表,因此您需要一种机制来防止竞争条件。在这种情况下,锁定机制是不合适的,因为它可能会成为您的应用程序的瓶颈。取而代之的是,让单个工作人员专门管理散列表,并让所有比较工作人员通过读取/插入队列向散列表管理器发送请求。由于管理器的工作相对较轻(存储、检索和删除图像指针),它应该能够在大多数时间保持在读取/插入队列的前面。

    当一个worker发出一个读请求时,它会等待管理器的回复(而不是当它发出一个插入请求时)。它可能会传递回调和 sleep ,或者输入自旋锁检查共享变量的“回复就绪”值(取决于您的编程环境,这可能归结为相同的事情)。当然,您根本不想让您的工作人员等待,但大多数等待将非常短暂,而且这种方法肯定会比全局锁定方法更快。

    在首次从哈希表中成功检索到图像后,管理器可以从表中删除该图像(因为只会请求该图像与后续图像进行比较)。管理器应该从哈希表中删除指针,而不是删除图像本身。您可以使用 reference counting以确定何时应从内存中完全清除图像。虽然引用计数需要锁定或原子化,但这不会成为瓶颈,因为在任何给定时间最多有两个工作人员访问图像,大多数情况下不会直接影响引用计数。

    备注

    在上面的设计中我没有讨论图像何时进入永久数据库。这很可能发生在生产者端,在图像进入第一个队列之前。或者,我讨论过的第三个队列中的数据库同步代理可能会这样做。您不想让您的比较 worker 或哈希表管理器承担此责任。

    如果您认为我的回答很有希望,我愿意提供额外的文档,例如(极简)流程图、工作人员的伪代码算法或粗略的数据流流量配置文件。

    关于architecture - 消息需要访问共享数据时的消息队列架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24944819/

    相关文章:

    c# - 架构问题 : Fluent NHibernate, 存储库模式和 ASP.NET MVC

    javascript - 使用 socket.io 排队

    c# - IPC——消息队列

    java - 在 opencv for android 中使用运动分析和对象跟踪进行瞳孔运动

    design-patterns - 我的代码去哪里了? Controller 、服务还是模型?

    java - 如何在 asp.net 响应中包含一个 java 页面?

    swift - RxSwift 正确使用变量

    线程退出 while 循环后的 android 守护进程线程

    iphone - xcode ios 6 摇动运动从以前的 View 调用 IBaction

    matlab - 计算空间共置的有效方法