后端开发人员的 6 大排队系统

已发表: 2019-08-09

您在寻找排队系统吗? 或者,也许您正在寻找更好的? 这里有你需要的所有信息!

排队系统是后端开发中保存最完好的秘密。

不想写一首赞美队列系统的诗,我会说一个初级后端开发人员在学会将队列集成到系统中之后就变成了一个中级后端开发人员。 队列改善了客户体验(我们将看到如何)、降低复杂性并提高系统的可靠性。

当然,对于流量接近于零的非常简单的 Web 应用程序和宣传册网站,队列可以是一个整体(如果您在典型的共享主机环境中,甚至无法安装),但重要的应用程序都将从队列中受益系统和大型应用程序在不涉及排队的情况下是不可能的。

在我们开始之前,一个免责声明:如果您已经对排队系统感到满意并且想要比较各种选项,那么接下来的几个介绍部分将导致大量睡眠。 所以请随意跳到前面。 介绍部分适用于那些对排队系统只有模糊概念或只是顺便听到这个名字的人。

什么是排队系统?

让我们从了解什么是队列开始。

队列是计算机科学中的一种数据结构,它模仿我们在我们周围看到的真实世界的队列。 例如,如果你去售票柜台,你会注意到你必须站在队列的末端,而队列开始的人会先拿到票。 这也就是我们所说的“先到先得”现象。 在计算机科学中,可以编写将它们的任务像这样存储在队列中的程序,并在相同的先到先得的基础上逐个处理它们。

请注意,队列本身并不进行任何实际处理。 它只是各种临时存储,任务等待它们被某些东西拾取。 如果这一切听起来有点过于抽象,请不要担心。 这一个抽象的概念,但我们将在下一节中看到清晰的示例。

为什么需要排队系统?

在不进行非常冗长的描述的情况下,我会说排队系统的主要需求是因为后台处理、并行执行和故障恢复。 让我们借助示例来看看这些:

后台处理

假设您正在运行一个电子商务营销活动,其中时间至关重要,并且您的应用程序被构建为在客户完成付款之前触发确认电子邮件并显示“谢谢”页面。 如果您连接的邮件服务器出现故障,网页就会死掉,破坏用户体验。

想象一下您会收到大量的支持请求! 在这种情况下,最好将此电子邮件发送任务推送到作业队列并向客户显示成功页面。

并行执行

许多开发人员,尤其是那些主要编写更简单、低流量应用程序的开发人员,都习惯于使用 cron 作业进行后台处理。 这很好,直到输入的大小变得如此之大以至于无法清除。 例如,假设您有一个 cron 作业来编译分析报告并将其通过电子邮件发送给用户,并且您的系统每分钟可以处理 100 个报告。

一旦您的应用程序增长并开始平均每分钟收到超过 100 个请求,它将开始越来越落后,并且永远无法完成所有工作。

在排队系统中,可以通过设置多个工作人员来避免这种情况,每个工作人员可以选择一项工作(每个工作包含 100 个要完成的报告)并并行工作以更快地完成任务。

从失败中恢复

作为 Web 开发人员,我们通常不会认为失败。 我们理所当然地认为我们的服务器和我们使用的 API 将始终在线。 但实际情况有所不同——网络中断太常见了,而且您所依赖的优秀 API 可能由于基础设施问题而停机(在您说“不是我!”之前,不要忘记大规模的 Amazon S3 中断)。 那么,回到报告示例,如果您的报告生成的一部分需要您连接到支付 API,并且该连接中断了 2 分钟,那么 200 个失败的报告会发生什么情况?

不过,排队系统确实涉及相当大的开销。 当您进入一个全新的领域时,学习曲线非常陡峭,您的应用程序和部署的复杂性会增加,并且排队的作业无法始终以 100% 的精度进行控制。 也就是说,在某些情况下构建没有队列的应用程序是不可能的。

顺便说一下,让我们看一下当今排队后端/系统中的一些常见选项。

雷迪斯

Redis 被称为键值存储,它只存储、更新和检索数据字符串,而不知道数据的结构。 虽然这在早期可能是正确的,但今天 Redis 拥有高效且非常有用的数据结构,如列表、排序集,甚至是 Pub-Sub 系统,使其非常适合队列实现。

Redis 的优点是:

  • 完全在内存中的数据库,导致更快的读/写。
  • 高效:可以轻松支持每秒100,000次以上的读/写操作。
  • 高度灵活的持久性方案。 您可以在发生故障的情况下以可能丢失数据为代价获得最大性能,也可以设置为完全保守模式以牺牲性能以保持一致性。
  • 开箱即用支持的集群

请注意,Redis 没有任何消息传递/队列/恢复抽象,因此您要么需要使用包,要么自己构建轻量级系统。 一个例子是 Redis 是 Laravel PHP 框架的默认队列后端,框架作者已经实现了一个调度器。

学习 Redis 很容易。

兔MQ

Redis 和 RabbitMQ 之间有一些细微的区别,所以让我们先把它们排除在外。

首先,RabbitMQ 有一个更专业、定义明确的角色,因此它的构建就是为了反映这一点——消息传递。 换句话说,它的最佳点是充当两个系统之间的中介,而 Redis 则不是这种情况,它充当数据库。 因此,RabbitMQ 提供了一些 Redis 中缺少的功能:消息路由、重试、负载分配等。

如果你考虑一下,任务队列也可以被认为是一个消息传递系统,其中调度程序、工作人员和作业“提交者”可以被认为是参与消息传递的实体。

RabbitMQ 具有以下优点:

  • 更好的消息传递抽象,如果你需要消息传递,减少应用程序级的工作。
  • 对电源故障和断电更具弹性(至少默认情况下比 Redis)。
  • 分布式部署的集群和联合支持。
  • 用于管理和监控部署的有用工具。
  • 支持几乎所有重要的编程语言。
  • 使用您选择的工具(Docker、Chef、Puppet 等)进行部署。

何时使用 RabbitMQ? 当您知道需要使用异步消息传递但还没有准备好解决此列表中其他一些排队选项的巨大复杂性时,我会说这是一个很好的选择(见下文)。

活动MQ

如果您进入企业领域(或构建高度分布式和大规模的应用程序),并且您不想一直重复发明轮子(并在此过程中犯错误),那么 ActiveMQ 值得一看.

这是 ActiveMQ 擅长的地方:

  • 它是用 Java 实现的,因此具有非常简洁的 Java 集成(遵循 JMS 标准)。
  • 支持多种协议:AMQP、MQTT、STOMP、OpenWire 等。
  • 开箱即用地处理安全、路由、消息过期、分析等。
  • 对流行的分布式消息传递模式的内置支持,为您节省时间和代价高昂的错误。

这并不是说 ActiveMQ 仅适用于 Java。 它拥有 Python、C/C++、Node、.Net 和其他生态系统的客户端,因此不必担心未来可能会崩溃。 此外,ActiveMQ 建立在完全开放的标准之上,构建自己的轻量级客户端应该很容易。

说了这么多,请注意 ActiveMQ 只是一个代理,不包括后端。 您仍然需要使用受支持的后端之一来存储消息。 我将它包含在这里是因为它不依赖于特定的编程语言(如其他流行的解决方案,如 Celery、Sidekiq 等)

亚马逊 MQ

Amazon MQ 值得在这里快速但重要地提及。 如果您认为 ActiveMQ 是满足您需求的理想解决方案,但又不想自己处理构建和维护基础设施,Amazon MQ 提供了一项托管服务来实现这一点。 它支持 ActiveMQ 所做的所有协议——在功能上完全没有区别——因为它在表面下使用了 ActiveMQ 本身。

Youtube 视频

优点是它是一项托管服务,因此您无需担心使用它以外的任何事情。 这对于 AWS 上的部署更有意义,因为您可以直接从您的部署中利用其他服务和产品(例如,更快的数据传输)。

亚马逊 SQS

我们不能指望亚马逊在关键基础设施方面坐以待毙,不是吗?

因此,我们有了 Amazon SQS,它是由知名巨头 AWS 提供的完全托管的简单队列服务(字面意思)。 再次强调,细微的差别很重要,所以请注意 SQS 没有消息传递的概念。 与 Redis 一样,它是一个简单的后端,用于在队列中接受和分发作业。

那么,您想在什么时候使用 Amazon SQS? 以下是一些原因:

  • 你是 AWS 的粉丝,不会碰其他任何东西(老实说,有很多这样的人,我认为这没有什么问题)。
  • 您需要一个托管解决方案,以确保故障率为零并且不会丢失任何作业。
  • 您不想构建一个集群并且必须自己监控它。 或者更糟的是,当您可以利用这段时间进行生产性开发时,必须构建监控工具。
  • 您已经在 AWS 平台上进行了大量投资,并且保持锁定状态具有商业意义。
  • 您需要一个集中的、简单的排队系统,没有任何与消息传递、协议等相关的绒毛。

总而言之,对于想要将作业队列合并到系统中而不必担心自己安装/监控事物的人来说,Amazon SQS 是一个不错的选择。

豆茎

Beanstalkd 已经存在了很长时间,并且是一个久经考验、快速、简单的作业队列后端。 Beanstalkd 的一些特点使其与 Redis 有很大不同:

  • 严格来说,这是一个工作排队系统,仅此而已。 你把工作推到它上面,这些工作后来被工作人员拉走。 因此,如果您的应用程序对消息传递的需求很小,那么您应该避免使用 Beanstalkd。
  • 没有像集合、优先级队列等高级数据结构。
  • Beanstalkd 是所谓的先进先出 (FIFO) 队列。 没有办法按优先级安排工作。
  • 没有集群选项。

所有这一切都说 Beanstalkd 为在单个服务器上运行的简单项目提供了一个灵活且快速的队列系统。 对许多人来说,它比 Redis 更快、更稳定。 因此,如果您在使用 Redis 时遇到了似乎无论如何都无法解决的问题,并且您的需求很简单,那么 Beanstalkd 值得一试。

结论

如果您已经阅读到这里(或到达此处略读),那么您很有可能对排队系统感兴趣或需要一个。 如果是这样,此页面上的列表将为您提供很好的服务,除非您正在寻找特定于语言/框架的队列系统。

我希望我能告诉你排队很简单而且 100% 可靠,但事实并非如此。 这很混乱,因为这一切都在后台并且发生得非常快(错误可能会被忽视并变得非常昂贵)。 尽管如此,队列仍然非常必要,而且您会发现它们是您武器库中的强大武器(甚至可能是最强大的武器)。 祝你好运!