消息队列概述
消息队列
消息队列源于消费者生产者模式,由生产者(Producer)、消息处理中心(Broker)、和消费者(Consumer)三者构成,一般有点对点和发布订阅两种模式:
- 点对点模式:多个生产者向同一个队列发送消息,每个消息只能由一个消费者消费
- 发布订阅模式:每个消息都能被多个订阅者获取和处理
核心功能
消息队列(MQ)提供三个核心功能:解耦、异步处理和削峰。
- 业务解耦 是指在分布式系统中,各组件或服务之间不直接通信,而是通过消息队列进行交互。这种方式使得各组件可以独立地进行更新和扩展,增强了系统的灵活性和可扩展性。例如,在电商平台中,订单服务和支付服务可以通过消息队列进行通信,互不影响,从而减少系统间的直接依赖。
- 异步处理 意味着系统的不同部分可以在不同的时间处理信息,从而提高整体效率和响应速度。在异步模型中,一个服务可以发送消息到队列,而不需要等待接收服务的响应。这种模式在高流量应用中尤其重要,如社交媒体平台中的消息传递。
- 流量削峰 指的是使用消息队列来应对短时间内的高流量。通过消息队列,可以平衡负载,确保系统在面对高峰流量时不会崩溃。例如,在促销或大型销售事件期间,消息队列可以帮助电子商务网站处理突发的大量订单请求。
特点
作为消息队列中间件,需要具备以下能力:
- 消息持久化:确保在系统故障时消息不会丢失。
- 高可用性和容错性:通过集群和故障转移机制确保系统的稳定运行。
- 消息确认和可靠传递:保证消息被正确接收和处理。
- 负载均衡:在多个生产者和消费者间有效分配消息。
- 扩展性:支持根据负载增加节点以扩展系统。
常见消息队列
RabbitMQ
少数几个支持 AMQP 协议的消息队列之一。很容易部署和使用。客户端支持多种编程语言。
但有以下缺点:
- 对消息堆积的支持不好,当大量消息积压的时候,会导致 RabbitMQ 的性能急剧下降。
- RabbitMQ的性能是这几个消息队列中最差的,大概每秒钟只能处理几万到十几万条消息。如果应用对消息队列的性能要求非常高,那么不要选择 RabbitMQ。
- RabbitMQ使用的编程语言是Erlang,扩展和二次开发成本高。
Kafka
Kafka与周边生态系统的兼容性是最好的没有之一,尤其在大数据和流计算领域,几乎所有的相关开源软件系统都会优先支持 Kafka。Kafka性能高效、可扩展良好并且可持久化。它的分区特性,可复制和可容错都是不错的。Kafka 使用 Scala 和Java 语言开发,设计上大量使用了批量和异步的思想,使得 Kafka能做到超高的性能。Kafka 的性能,尤其是异步收发的性能,是三者中最好的,但与 RocketMQ 并没有量级上的差异,大约每秒钟可以处理几十万条消息。
但有以下缺点:
- 同步收发消息的响应时延比较高,因为当客户端发送消息的时候,Kafka 采用的是批量发送,在它的 Broker中,很多地方都会使用这种先攒一波再一起处理的设计。当业务场景中每秒钟消息数量没有那么多的时候,Kafka 的时延反而会比较高。所以,Kafka 不太适合在线业务场景。topic达到上百个时,吞吐量会大幅下降。
高性能的原因:
- 磁盘顺序读写:保证了消息的堆积
- 顺序读写,磁盘会预读,预读即在读取的起始地址连续读取多个页面,比随机读写的速度快不少,因为免去了磁盘寻道的时间
- 使用零拷贝:避免 CPU 将数据从一块存储拷贝到另外一块存储的技术。
- 分区分段+索引:Kafka的message消息实际上是分布式存储在一个一个小的segment中的,每次文件操作也是直接操作的segment。为了进一步的查询优化,Kafka又默认为分段后的数据文件建立了索引文件,就是文件系统上的.index文件。这种分区分段+索引的设计,不仅提升了数据读取的效率,同时也提高了数据操作的并行度
- 批量压缩/读写:多条消息一起压缩,降低带宽
- 直接操作page cache,而不是JVM、避免GC耗时及对象创建耗时,且读写速度更高,进程重启缓存也不会丢
RocketMQ
RocketMQ 有着不错的性能,稳定性和可靠性,具备一个现代的消息队列应该有的几乎全部功能和特性,并且它还在持续的成长中。RocketMQ 有非常活跃的中文社区,大多数问题可以找到中文的答案。RocketMQ 使用 Java 语言开发,源代码相对比较容易读懂,容易对RocketMQ 进行扩展或者二次开发。RocketMQ 对在线业务的响应时延做了很多的优化,大多数情况下可以做到毫秒级的响应。
评论