消息队列|青训营笔记

235 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记

什么是消息队列

消息队列(Message Queue,MQ),指保存消息的一个队列,本质是个队列,但是支持高吞吐、高并发,并且高可用。消息队列是一个生产者-消费者模型,可以有效解决应用解耦、异步消息、流量削峰等问题。

业界常见的消息队列

  • Kafka:分布式的、分区的、多副本的日志提交服务,在高吞吐场景下发挥较为出色
  • RocktMQ:低延迟、强一致、高性能、高可靠、万亿级容量和灵活的可扩展性,在一些实时场景中运用较广
  • Pulsar:是下一代云原生分布式消息流平台,集消息、存储、轻量化函数式计算为一体、 采用存算分离的架构设计
  • 字节BMQ:和Pulsar架构类似,存算分离,初期定位是承接高吞吐的离线业务场景,逐步替换掉对应的Kafka集群

如何使用Kafka

graph TD
创建集群 --> 新增Topic --> 编写生产者逻辑 --> 编写消费者逻辑

基本概念

  • Topic: 逻辑队列,不同Topic可以建立不同的partition
  • Cluster: 物理集群,每个集群中可以建立多个不同的Topic
  • Producer: 生产者,负责将业务消息发送到Topic中
  • Consumer: 消费者,负责消费Topic中的消息
  • ConsumerGroup: 消费者组,不同组Consumer消费进度互不干涉
  • Offset: 消息在partition内的相对位置信息,可以理解为唯一ID,在partition内部严格递增
  • Replica: 每个分片有多个Replica(副本),Leader Replica将会从ISR(In-Sync Replicas)中选出

一条消息的流程

graph LR
Producer --生产--> Broker --消费--> Consumer

Kafka的特点

Producer采用了批量发送数据压缩的方法来提高Kafka的吞吐量

Broker采用了顺序写消息索引以及零拷贝的方法来提高性能。

对于一个Consumer Group,多个分片可以并发的消费,以此提高消费的效率。但需要解决 ConsumerPartition的分配问题,即对于每一个Partition来说,该由哪一个Consumer来消费。除了手动分配以外,Kafka采用了Rebalance的方法提供自动分配。简单来说,在Broker集群中,对于不同的Consumer Group来讲,都会选取一台Broker当作Coordinator,而它的作用就是帮助Consumer Group进行分片的分配。采取该方式后,即使Consumer Group中有发生宕机,或者有新的Consumer加入,Kafka会自动进行重新分配,达到稳定的消费状态。

问题

  • 运维成本高
  • 对于负载不均衡的场景,解决方案复杂

  • 没有自己的缓存,完全依赖Page Cache

  • Controller和Coordinator和Broker在同一进程中,大量IO会造成其性能下降

    为了解决这些问题,字节跳动自研的ByteMQ (BMQ)采取了一定的策略进行优化。

BMQ

ByteMQ(BMQ)是一个兼容Kafka协议,存算分离,云原生的消息队列。

运维操作对比

具体操作KafkaBMQ
重启需要数据复制,分钟级重启重启后可直接对外服务,秒级完成
替换需要数据复制,分钟级替换,甚至天级别替换后可直接对外服务,秒级完成
扩容需要数据复制,分钟级扩容,甚至天级别扩容后可直接对外服务,秒级完成
缩容需要数据复制,分钟级缩容,甚至天级别缩容后可直接对外服务,秒级完成

BMQ在重启、替换、扩容、缩容这些运维操作上的效率十分高,这得益于其架构的设计。实际上对于所有节点的变更操作,都仅仅只是集群元数据的变化,通常情况下都能秒级完成,而真正的数据存储在下层分布式文件存储系统中,因此才不需要考虑数据复制带来的时间成本。这与Kafka相比,是架构上的先进之处,也是云原生的体现。