如何将处理服务器与数据库分离
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成功即可。另一种方法是在写入队列时简单地重试指数退避。这应该有助于在写入队列时大大减少错误。以上是关于如何将处理服务器与数据库分离的主要内容,如果未能解决你的问题,请参考以下文章