队列是一种数据结构,它可以模仿我们在真实世界的队列。例如,如果你去排队购票,你必须站在队列的最后,而队列开头的人将优先购买。这就是我们所说的“先到先得”的现象。在编程中,可以编写任务存储在队列中的程序,并以先到先得的方式逐个处理它们。而队列本身不进行任何实际处理,它只是临时存储的各种任务。我们对队列系统的主要需求是因为后台处理,并行执行和故障恢复。比如:
后台处理
假设你正在运行电子商务的营销,那么时间就至关重要了。如果应用已构建,以便在客户完成付款之前触发确认电子邮件,并显示回复页面。如果你连接的邮件服务器已关闭,则网页无法打开,而影响用户体验。想象一下当获得的大量支持请求的情况下,最好将电子邮件发送任务推送到作业队列。
并行执行
许多开发人员,特别是那些主要编写简单,流量较低的应用的开发人员,习惯于使用cron作业进行后台处理。例如,假设有一个cron作业,它编译分析报告并通过电子邮件发送给用户,并且系统每分钟可以处理100个报告。一旦应用增长并且平均每分钟开始获得超过100个请求,处理效率将越来越滞后,那么将永远无法完成所有工作。
在队列系统中,可以通过设置多个工作人员来避免这种情况,每个工作人员可以选择一个工作(每个工作包含100个报告)并且并行工作以更快地完成任务。
故障恢复
作为Web开发人员,我们会认为服务器和使用的API将始终连接,而现实情况则不同。网络中断非常普遍,我们所依赖的优秀API可能因基础设施问题而崩溃。因此,回到上面的报告举例,如果生成报告的部分内容要求你连接到API,并且该连接已关闭了2分钟,那么200个报告失败的情况会怎样?
需要指出的是,队列系统的学习确实十分耗费精力,它学习曲线陡峭,应用和部署的复杂性增加,队列的作业无法始终以100%的精度控制。所以,该如何选择趁手的队列系统?以下将推荐五个适合后端开发人员的队列系统。
Redis
Redis是键值存储系统,以前它只存储,更新和检索数据字符串,而不了解数据结构。但今天Redis拥有高效且非常有用的数据结构,如列表,有序集,甚至是Pub-Sub系统,这使得它非常适合于队列实现。
Redis的优势:
完全的内存数据库,从而实现更快的读/写。
高效:每秒可轻松支持超过100000次读/写操作。
高度灵活的持久性方案。可以在出现故障时以可能的数据丢失为代价获得最大性能,或者以完全保守的模式设置以牺牲性能以保持一致性。
集群支持开箱即用
需要注意的是,Redis没有任何消息传递/排队/恢复抽象,因此你需要使用软件包或自己构建轻量级系统。一个例子是Redis是Laravel PHP框架的默认队列后端,其中调度程序已由框架作者实现。
RabbitMQ
Redis和RabbitMQ之间有一些细微的区别,所以让我们先把它们弄清楚。
首先,RabbitMQ具有更专业,定义明确的角色,因此它的构建反映了消息传递。换句话说,它充当了两个系统之间的中介,而Redis则不是这种情况,它充当数据库。因此,RabbitMQ提供了Redis中缺少的一些工具:消息路由,重试,负载分配等。
任务队列也可以被认为是一个消息传递系统,其中调度程序,工作者和作业“提交者”可以被认为是参与消息传递的实体。
RabbitMQ的优势:
消息传递的更好抽象,如果你需要消息传递,则减少应用级别的工作。
对电源故障和停电更具弹性(至少在默认情况下比Redis更强)。
集群和联合支持分布式部署。
用于管理和监控部署的有用工具。
几乎支持所有的编程语言。
可使用Docker,Chef,Puppet等进行部署。
什么时候使用RabbitMQ?当你需要使用异步消息传递,但是还没有准备好解决这个列表中某些其他队列选项的高度复杂性时,RabbitMQ是一个很好的选择(见下文)。
ActiveMQ
如果你要构建高度分布式的大型应用时,并且你不希望一直重新发明轮子,那么ActiveMQ值得一试。
ActiveMQ的优势:
它是用Java实现的,因此具有非常简洁的Java集成(遵循JMS标准)。
支持多种协议:AMQP,MQTT,STOMP,OpenWire等。
开箱即用处理安全性,路由,消息过期,分析等。
为流行的分布式消息传递模式提供Baked-in支持,节省你的时间和代价高昂的错误。
ActiveMQ并不是仅适用于Java。它拥有Python,C/C ++,Node,.Net和其他生态系统的客户端。此外,ActiveMQ建立在完全开放的标准之上,构建自己的轻量级客户端应该很容易。不过,ActiveMQ不包括后端。你仍然需要使用其中一个受支持的后端来存储消息。
Amazon MQ
如果你认为ActiveMQ是能满足需求的理想解决方案,但又不想自行构建和维护基础架构,那么Amazon MQ提供了托管服务来实现这一目标。它支持ActiveMQ所做的所有协议,功能完全没有区别。
优点是它是一个托管服务,因此除了使用它之外,你不必担心任何其他问题。对于AWS上的那些部署更有意义,因为你可以直接从部署中利用其他服务和产品(例如,更快的数据传输)。
Beanstalkd
Beanstalkd是一个经过实战考验,快速,简单的后端队列系统。Beanstalkd的一些特性使其与Redis有很大不同:
它严格来说是一个工作排队系统而已。如果你的应用对消息传递的需求很小,那么请避免使用Beanstalkd。
没有高级数据结构,如集合,优先级队列等。
Beanstalkd被称为先进先出(FIFO)队列。没有办法按优先顺序安排工作。
没有集群选项。
所有这些都使得Beanstalkd能为服务器上的简单项目提供一个灵活快速的队列系统。对于许多人来说,它比Redis更快,更稳定。因此,如果你遇到Redis问题,无论如何都无法解决,而且你的需求很简单,那么Beanstalkd值得一试。