消息队列原理 | 青训营笔记

70 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第12天。

消息队列

案例一:

本人想买东西,搜索直播间,点击直播间,搜索行为会被记录。

案例二:

很多人想要购买同一个商品,发起订单到处理订单,可能只能同时处理10个订单。

思考如果发生:系统崩溃、服务处理能力优先、链路耗时长、以及日志应该如何处理。

解决方案:添加消息队列。

在日志处理中:

Log->消息队列->LogStash->ES->Kibana

概念

消息队列是指保存消息的容器,本质上是一个队列,但是这个队列需要支持高吞吐、高并发并且要高可用。

发展历程

  • TIB:消息队列诞生于1985年,服务于金融机构和新闻机构。
  • WebSphere:诞生于1993年,商业消息队列平台市场的主要玩家
  • MSMQ:微软发布于1997年。
  • JMS:诞生于2001年本质上是一套JAVA API。
  • AMQP:发布于2004年,同年RabbitMQ面试。
  • Kafka:2010年由Linked开源。
  • RocketMQ:2011年阿里中间件团队。
  • Pulsar:2012年诞生于Yahoo内部。

消息队列Kafka

使用场景

搜索服务、直播服务、订单服务、支付服务

日志信息、Metrics数据、用户行为。

如何使用Kafka

首先创建Kafka集群->新增Topic->编写生产者逻辑->编写消费者逻辑。

基本概念

Topic:不同的业务场景可以看作不同的Topic

Cluster:物理集群,每个集群中可以建立多个不同的Topic。

Producer:生产者,负责将业务信息发送到Topic中。

Consumer:消费者,负责消费Topic中的消息。

ConsumerGroup:消费者组,不同组的Consumer互不干涉。

Offset:消息在partition中的相对位置,可以理解成唯一ID,在partition内部严格递增。

Replica:每个分片有多个Replica,Leader Replica将会从ISR中选出。

从消息的角度观察Kafka

Producer->Broker->Consumer

Producer->Message->Broker

Broker->Success->Producer

Broker中采用顺序写的形式,提高写入效率。

Consumer-消息的接收端

对于一个Consumer Group来说,多个分片可以并发的消费,可以大大提高消费的效率,但是需要解决的问题是,Consumer和Partition的分配问题,也就是对于每一个Partition来讲,该由哪一个Consumer来消费的问题。对于这个问题,我们一般有两种解决办法,手动分配与自动分配。

帮助Kafka提高吞吐和稳定性的功能

Producer:批量发送、数据压缩

Broker:顺序写,消息索引,零拷贝

Consumer:Rebalance

Kafka重启操作

如果对一个机器进行重启,首先要关闭一个Broker,如果此时该Broker上存在副本的Leader,那么该副本将发生Leader切换,切换到其他节点中并在ISR中的Follower副本。而此时,因为数据在不断地写入,对于刚刚关闭重启的Broker来说,和新的Leader之前一定会存在数据的滞后,此时这个Broker会追赶数据,重新加入ISR中,当数据追赶完成之后,我们需要切回Leader,这一步称为prefer leader,这一步的目的是为了避免,在一个集群长期运行之后,所有的leader都分布在少数的节点之上,导致数据的不均衡。

Kafka 负载不均衡

在这个场景中,同一个Topic有4个分片,两个副本,可以看到,对于分片1来说,数据量明显是要比其他的分片大的,当我们机器IO达到瓶颈时,可能需要把第一台Broker上面的Partition3迁移到其他负载小的Broker上。

Kafka存在的问题
  • 运维成本高。
  • 对于负载不均衡的场景,解决方案复杂。
  • 没有自己的缓存,完全依赖Page Cache。
  • Controller和Coordinator和Broker在同一进程中,大量IO会造成其性能下降。