- 1 消息队列概述
- 1.1 下订单-同步&异步
- 1.2 消息队列分类
- 1.2.1 有Broker的MQ
- 重Topic
- 轻Topic
- 1.2.2 无Broker的MQ
- 2 Kafka的基本概念
- 2.1 生产&消费
- 2.1.1 两种消费方式
- 2.1.2 单播&多播消息
- 2.2 主题和分区
- 2.3 _consumer_offsets
先来看一个例子,以电商网站购买东西下单为例
用户在手机上下单后,需要调用一系列服务才能完成整个下单过程
如订单服务,库存服务,收单服务,金融服务,积分服务等
如果通过同步方式来处理:
同步的方式明显有若干弊端:
1,响应时间长 调用链路越长,经过的Service越多,同步消耗的时间越久 每次调用Service时都要先通信再执行,这个环节越多tp99越高 2,稳定性不够 调用过程中但凡有一个服务受到了网络抖动等影响 整个链路成功执行的耗时都会受到影响,链路中经过的每个服务节点都影响最终结果
为此,如果通过异步方式来处理:
相比同步,异步的方式在建单时生产一条消息交给消息队列,然后就给用户返回建单成功的结果
消息被放在消息队列的各个队列中,由不同的服务来取得消息消费执行不同的动作
这个过程,相比同步的优点在于:
1,明显提升系统吞吐量 2,明显提升系统响应速度 3,即使有一个服务执行失败,也可以通过分布式事务来保证最终结果是成功的1.2 消息队列分类
MQ的定义:MessageQueue,消息中间件,MQ的直接目的是为了通信,屏蔽底层复杂的通信协议
通常一个分布式系统中通信要么采用HTTP,要么用RPC 但这两种协议都相当原始
MQ在其基础上构建一个简单易用的协议,即生产者/消费者模型,MQ定义了两个对象,发送数据的是生产者,接收数据的是消费者,并提供一个SDK可以自定义生产者和消费者实现消息通信而屏蔽底层通信协议
MQ可以看作更高级的Socket
消息队列又有不同的产品,如rabbitMQ,rocketMQ,ZeroMQ,Kafka等
这些消息队列中间件的区别在于有无Broker,Broker的作用类似于一个中转站,所有消息都由它中转
生产者将消息发给消息队列后,Broker将这些消息主动推送给相应消费者(或由消费者从队列中轮询取)
Kafka和JMS属于这种类型,生产者会将key+data发送给Broker,由Broker比较key后决定给哪些消费者
Topic某种意义上就是key,生产者发送key+data,意为让Broker将data放入key对应的queue中
RabbitMQ属于这种类型,内部可以使用Topic也可以不用
ZeroMQ属于这种类型,每个节点既是生产者又是消费者,节点间通信将消息通过socket发送到彼此的队列中
Kafka是一个分布式的,支持分区的,多副本的依赖ZK管理的分布式消息系统
2.1 生产&消费Broker: 消息中间件处理节点,一个Kafka节点就是一个Broker 一个或多个Broker可以组成Kafka集群 Topic: Kafka根据Topic对消息进行归类,发布到Kafka集群的每条消息都需要指定一个Topic Producer: 消息生产者,向Broker发送消息 Consumer: 消息消费者,从Broker读取消息
Topic主要对消息进行归类,区分消息应该给谁消费
消费有两种方式:
1,从最后一条消息的偏移量+1 开始消费
此种方式生产者先生产一些消息,然后消费者上线开始消费
如果先前生产者生产了3条消息,那么消费者只能从第4条消息开始消费
2,从头开始消费,很容易理解
消费者上线时,从Topic中依次取生产者发的消息,一条不漏
消息是会被保存的,根据偏移量被消费
关于生产-消费的几个注意点:
1,生产者将消息发送给Broker,Broker会将消息保存在本地的日志文件中 2,消息的保存是有序的,通过offset来描述消息的有序性 3,消费者消费消息时,也是通过offset来描述当前要消费的消息的位置2.1.2 单播&多播消息
在一个Kafka的Topic中,启动一个Producer生产,两个同组的Consumer消费
这条消息是否会同时被两个Consumer消费?
答案是否,这种就是单播消息,在这里引入ConsumerGroup的概念
ConsumerGroup:消费组,可以包含多个订阅了同一Topic的Consumer
在一个Kafka的Topic中,启动一个Producer生产,两个不同组的Consumer消费
这条消息是否会同时被两个Consumer消费?
答案是可以,这种就是多播消息
单播消息:不同Consumer订阅同一个Topic,且处于同一个ConsumerGroup 这个ConsumerGroup中只有一个Consumer能消费消息 多播消息:不同Consumer订阅同一个Topic,且处于不同的ConsumerGroup 那么每个ConsumerGroup中都能有一个Consumer消费消息2.2 主题和分区
主题Topic是一个逻辑概念就是为了消息种类的区分
不同Topic被订阅该Topic的消费者消费
但一个主题中存储的消息量是非常大的,可能几T的消息都是有可能的
这些消息都是存在log日志中的,为了解决该文件过大的情况
因此可以通过分区Partition的设置,来分布式存储这些消息,Partition是物理存在的
如一个Topic创建了三个Partition,那么Topic中的消息会存储在这三个Partition中
通过分区存储消息的好处:
1,分布式存储,解决统一存储文件过大的问题 2,提高了读写吞吐量,生产/消费可以在多个分区中进行2.3 _consumer_offsets
Kafka内部自己创建了_consumer_offsets主题包含了50个分区
这个主题用来存放Consumer消费某个Topic的偏移量
如某个ConsumerGroup中有两个Consumer,分别为Consumer1和Consumer2
当前Topic中有100条消息待消费,Consumer1消费了50条后宕机
此时由Consumer2继续消费,此时Consumer2从第51条开始消费
Consumer2能从第51条开始消费,是因为Kafka的_consumer_offsets中记录了已消费信息的偏移量
这些已消费信息偏移量是Consumer1每次消费后都会提交的
提交的格式是KV,key是ConsumerGroup+Topic+分区号,value是当前被消费的消息offset
每个Consumer都会把消费的Topic的偏移量自主上报给_consumer_offsets主题
以记录Topic内消息的消费进度,保证队列式消费
每个Broker中设置了50个_consumer_offsets分区,是因为每个Broker中有很多Topic
且会有很多Consumer来消费,每个Consumer每消费一条都要提交消费消息位置+消费进度
为此50个分区能让Consumer并行的提交,以提高效率
至于Consumer去提交到哪个_consumer_offsets分区
由hash(ConsumerGroup)%_consumer_offsets主题分区数决定
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)