kafka
消息队列是什么,解决什么样的问题,有什么常见的应用场景
MQ(message queue)消息队列是本质上是队列(先进先出的数据结构),生产者将消息放到队列上,消费者通过,消息的消费者通过拉取或者订阅推送的机制来获取消息。
解决的问题:
mq本质上是一种通信机制,它屏蔽到了底层繁琐的http或者tcp通信的细节,提供一套消息队列机制。
解耦:当一个业务需要多个模块的配合,一条消息需要多个系统的处理时,可以使用消息队列机制降低整个系统的耦合度。
异步:主任务执行结束之后,从业务通过异步的方式进行处理,降低系统的响应时间,提高用户体验。
削峰:在多线程的系统当中业务采用异步的方式处理,提高整个系统的性能,避免系统瘫痪。
消息队列的分类
当前消息的队列的分类,当前消息队列的分类大致上分为有broker的消息队列和无broker的消息队列(代表为zero MQ),有broker的队列又分为重Topic(kafka,Rocket MQ,Active MQ)的队列和轻Topic的队列(Rabbit MQ)。
kafka的基本介绍(给一个定义)
kafka是一个基于zookeeper协调的,支持分区的多副本的分布式系统
kafka的基本概念(架构)
kafka是一个基于生产者和消费者的消息队列,其中的消息队列由broker(中间件处理节点)存储和管理,生产者负责将消息发送到broker上,消费者从broker上消费消息。
broker中的各种概念
Topic
topic是消息的主题,kafka使用topic将消息分类
默认主题:
kafka中存在_consumer_offset这个topic,它用于记录所有的consumerGroup的消费偏移量,将ConsumerGroupID+Topic+partition作为key将offset作为值存储。由于这个主题可能会引起大并发问题所以kafka默认将其分为50个分区来存储,并且根据hash(consumer——groupid)来计算消息锁使用的分区。
Partition
物理上的概念,⼀个topic可以分为多个partition,每个partition内部消息是有序的 。
使用partition的的好处主要是可以将 分布式存储和并发写。
所有的消息全部存储在data/kafka-logs/topic-partition中
副本
副本顾名思义就是分区的备份。
如果存在多个broker就可以为分区设置多个备份,分区中有这么几个需要知道的概念。replicas代表当前分区的所有节点,isr代表已同步的节点是,leader和flower是相对的概念,kafka会在多个副本中选取一个副本作为leader,所有对这个分区的读写操作都在再leader上完成,并且在读写完成之后将消息同步到flower上,当leader挂掉了就会使用选举机制启动其中一个flower作为新的leader。
producer细节
基本的消息发送流程:
设定消息发送的broker地址序列化和反序列化规则之后,通过这些规则创建一个Producer用于发送消息。在发送消息的时候会在producer端创建一个32k的缓冲区,并且有一个专门的线程去缓冲区中获取消息并且发送,当消息数据满16k或者时间到达10ms时会发送数据。
发送的方式:
消息发送的方式分为同步发送和异步发送两种,同步发送时业务会暂停等待ack的回复,如果没有收到回复就会默认重新发送,如果收到ack需要查看当前ack的配置(配置有三种0代表只要收到ack不管broker的情况直接代表消息发送成功,1代表需要broker中将leader的消息同步到log中,-1则代表不但需要同步到leader中还需要同步到flower中至于同步到几个flower中由min-insync-replicas指定。这三种ack的设置性能上递减,安全性上递增。)。异步发送的方式就是在发送消息的时候不会阻塞等待,而是使用一个回调方法来后续跟踪消息的情况,这种方式容易丢失消息。
发送到的地方:
在发送的时候可以指定分区也可以使用一个key使用hash算法指定分区。
consumer细节
consumergroup的概念:多个消费者属于一个消费者组,一个消费者组中的消费者只能消费一次同一条消息。我们可以查看当前消费者组中的消费者有哪些,每个消费者的current_offset,log_end_offset,lag等
单播消息和多播消息:
单播消息值得是一条消息只能被一个消费者组中的一个消费者消费也就是一个消息只被消费一次,多播消息指的是可以创建多个消费者组这样多个消费者组中就能够有多个消费者能够消费同一条消息。
消费者和分区的关系:
消费者和分区的关系是一个一对多的关系一个消费者可以消费多个分区但是一个分区只能由一个消费者消费,所以建议消费者的数量应该小于分区的数量否则多余的消费者就只能当做备选。
如何消费:
基本的消费流程
最基本的消费流程就是指定好需要消费的broker的地址,消费组信息,序列化反序列化的配置之后创建一个消费者。然后消费者订阅主题之后消费。
指定分区消费
消费过程中可以指定分区消费,回溯消费指定偏移量消费或者指定时间点消费。
poll的流程
poll消息的流程大致是这样的我们可以根据消费者的消费能力指定每次poll的消息数量和一次长轮询时间,当poll的消息数量达到我们设置的值或者时间达到长轮询的时间之后poll1结束。在poll的过程当中消费者如果消费能力太差导致两次poll的时间超出设置的默认值就会发生rebalance,或者维持的心跳包没有按时发送给broker也会发生rebalance。
消费结束后offset提交方式
offset的提交方式分为自动提交和手动提交两种,自动提交指的是每次poll到消息之后直接提交offset,这回出现消息丢失的问题。手动提交又分为手动同步提交和自动异步提交,区别就在于是否阻塞。
如果有新的消费者组加入了怎么办
kafka的一些机制
controller机制:
根据zk中创建broker节点的时间,最快创建的一个broker会被选择作为controller,它的作用就是在leader挂掉的时候通过在isr中选择同步性能好的一个flower作为leader继续工作,还有就是在新增分区或者broker的时候在各个broker之间同步。
rebalance机制:
它讲述的是分区和消费之组中消费者的关系,当消费者没有指定分区消费的时候,或者消费者和分区的关系发生变化时会触发这个机制。它有range(根据公式来计算分配的分区个数),轮询分配以及sticky(在不改变原来分配的基础上重新分配)三种方式
HW和LEO
LEO(log_end_offset):最后消费位置。
HW指的是高水位,kafka需要维持一个高水位,就是说当所有的消息都到达高水位之后才能暴露给消费者消费,否则会出现重复消费的情况。
面试题
如何保证顺序消费
保证一个消费者,一个分区
如何保证消息不重复消费
两种方式,第一种是关闭重试机制,第二种是在消费者端设置一些幂等性的操作,比如说分布式锁,或者创建联合主键。
如何保证消息丢失
消息生产者采用同步发送的方式,1,-1.消息的消费者在消费的时候采用手动提交。
消息积压的问题
优化消费的速度,多线程,多消费者。消息转发。