分布式消息队列的设计要求


学习使用一个虚构的解决方案设计分布式消息队列的要求。

要求

分布式消息队列中,数据驻留在几台计算机上。我们的目标是设计出一个具有以下功能和非功能要求的分布式消息队列。

功能要求

以下是客户端应能执行的操作:

  • 创建队列:客户端应能够创建一个队列并设置一些参数,例如队列名称、队列大小和最大消息大小。通常,像Amazon Simple Queue Service(SQS)和Microsoft Messaging Queue(MSMQ)这样的流行服务允许的最大大小分别为256KB和4MB。那么我们如何发送超出预定义大小的消息呢?有多种方法可以用于发送大于指定允许大小的消息。例如,一种方法是将消息分成小块发送,在接收方重新组合。但是,这种方法会在发送方和接收方增加额外的复杂性。 Amazon SQS通过提供扩展库,用户可以通过调用几个API(包括AmazonS QSExtendedClientExtendedClientConfiguration等)来发送包含对Amazon S3中消息有效负载的引用的消息。同样,Microsoft MSMQ提供一个MQSendLargeMessage API,用于发送大于4MB的消息作为XML文档。因此,我们将假定我们的系统支持Amazon或Microsoft的一种策略,而忽略此讨论。

  • 发送消息:生产者实体应能够发送消息到其专用队列。

  • 接收消息:消费者实体应能够从其相应的队列接收消息。

  • 删除消息:在成功处理消息后,消费者进程应能够从队列中删除消息。

  • 删除队列:客户端应能够删除特定队列。

非功能要求

我们设计分布式消息队列时应遵守以下非功能要求:

  • 持久性:系统接收到的数据应是持久的,不应丢失。生产者和消费者可以独立故障,具有数据持久性的队列对于使整个系统工作至关重要,因为其他实体依赖于队列。

  • 可扩展性:系统需要具有可扩展性,能够处理增加的负载、队列、生产者、消费者和消息数量。同样,当负载减少时,系统应能够相应地收缩资源。

  • 可用性:系统应具有高可用性,以便接收和发送消息。即使其中一个或多个组件故障,它也应继续无间断地运行。

  • 性能:系统应提供高吞吐量和低延迟。

单服务器消息队列

在我们开始制定分布式消息队列的设计之前,我们应该回顾一下队列在单台服务器内的使用方式,其中生产者和消费者进程也在同一节点上。生产者或消费者可以通过获取锁定机制来访问单服务器队列,以避免数据不一致。队列被认为是一个关键部分,只有一个实体,生产者或消费者,可以同时访问数据。

然而,今天的分布式系统范式中有多个方面限制我们使用单服务器消息队列。例如,硬件或网络故障发生时,协作进程(生产者和消费者)变得不可用。此外,随着锁上的内容变得越来越多,性能也会遭受重大打击。此外,它既不可扩展也不具有持久性。多个生产者和消费者通过一个单一的消息队列进行交互

警告

问题

问题:能否将单服务器消息队列的设计扩展到分布式消息队列?

答案

单服务器消息队列存在以下缺点:

高延迟:与单服务器消息队列类似,生产者或消费者获取锁来访问队列。因此,当许多进程尝试访问队列时,该机制成为瓶颈,这增加了服务的延迟。

低可用性:由于消息队列未进行复制,生产者和消费者过程可能在发生故障时无法访问队列。这降低了系统的可用性和可靠性。

缺乏耐用性:由于缺乏复制,队列中的数据可能在系统故障时丢失。

可扩展性:单服务器消息队列可以处理有限数量的消息、生产者和消费者。因此,它不可扩展。

要将单服务器消息队列的设计扩展到分布式消息队列,我们需要做出大量努力以消除上述缺点。

我们将使用以下构建块来设计分布式消息队列:

数据库将需要用于存储队列和用户的元数据。

缓存非常重要,可以保留频繁访问的数据,无论是与用户还是与队列元数据相关的数据。

负载均衡器用于将传入请求定向到存储元数据的服务器。

在我们讨论消息队列时,我们关注了它们的功能和非功能要求。在继续设计分布式消息队列的过程之前,我们有必要讨论一些可能影响设计的关键考虑和挑战。