如何将处理服务器与数据库分离

Posted

技术标签:

【中文标题】如何将处理服务器与数据库分离【英文标题】:How to decouple processing servers from database 【发布时间】:2021-04-07 03:41:37 【问题描述】:

我正在构建一个应用程序,它通过 Web 界面接收用户的请求,然后执行一些处理并在可用时返回结果。

以下是当前架构的简单概述:

Web 应用程序将请求添加到 MongoDB 中的多个集合,并将 processed 字段设置为 False。然后每个集合都有处理服务器,它们轮询他们的集合以检查是否有任何未处理的条目。如果是,服务器然后执行需要一些时间和一些成本(外部 API 调用)的处理,然后将结果保存回数据库(output_data)并将processed 设置为 True。

现在,我遇到的问题:

    我无法为每个模块扩展处理服务器,因为如果我运行两台服务器,那么同一个条目可能会被处理两次,并且会给我带来更多成本。

    我还想将处理服务器与数据库分离,因为我也想将相同的处理服务器与不同的数据库一起使用(例如:针对不同的客户)

我不太了解队列和发布/订阅架构。我认为某种队列架构对实现上述目标很有用,但不确定如何处理重复消息。

请让我知道哪种架构有助于避免上述问题。我希望解决方案与云提供商无关,但如果真的需要,我想使用 AWS。

更新: 我目前的开发堆栈是 Python、Flask、MongoDB、Docker。

【问题讨论】:

网络应用真的在等待结果吗?或者它是一劳永逸,然后提供一种单独的方法来检查结果?换句话说,该部分流程是否旨在支持异步方法? 是的,Web 应用程序是异步的,用户稍后可以通过从列表中选择请求来查看结果。我发现下面亚历克斯的答案非常适合我的用例 【参考方案1】:

我建议您使用消息队列,它将解决您的许多问题。例如,RabbitMQ,在这里你可以找到 python libraries 来使用它。

您的工作进程将无需轮询,而是等待新消息到达,从而消除了重复处理的问题。他们还可以将结果发送回消息队列,保存工作人员会将它们保存到任何(不同的)数据库中。我发现引入消息队列与publish/subscribe 模式的架构非常契合。

【讨论】:

【参考方案2】:

您可以在以下架构中根据您的要求使用不同的队列。

Redis 发布/订阅:https://redis.io/topics/pubsub

Kafka/RabitMQ:您可以检查哪种工具适合您的需求。

AWS SQS:https://aws.amazon.com/sqs/(如果您想使用队列,无需安装和维护的麻烦。不同的云提供队列机制。

在内存队列中:缺点是这是易失的,队列将是 系统重新启动/崩溃时丢失。如果你有一些可以使用 如果需要,重新创建队列的机制。

【讨论】:

如何处理后端向队列发送消息失败但将请求id存入数据库成功的情况? 您可以从DB发布bin日志并推送到Queue,保证Backend只需要发布到DB成功即可。另一种方法是在写入队列时简单地重试指数退避。这应该有助于在写入队列时大大减少错误。

以上是关于如何将处理服务器与数据库分离的主要内容,如果未能解决你的问题,请参考以下文章

大型网站架构演进数据库与应用服务器分离

前后端分离微服务架构如何设计

大型网站架构演进数据库与应用服务器分离

存储优化--分区与冷热分离

如何使用两台服务器实现主从同步与数据读写分离

MySQL主从复制与读写分离