Golang 消息队列面试题与答案

Golang
298
0
0
2023-08-22
标签   Golang面试

Golang 消息队列面试题与答案

一、目录:

1、 kafka 是什么?主要应用场景有哪些?

2、和其他消息队列相比、 kafka 的优势在哪里?

3、什么是 producer、consumer、broker、topic、partition

4、 kafka 多副本机制 了解吗?

5、 kafka 多分区( partition )以及多副本( replica )机制有什么好处呢?

6、 zookeeper kafka 中的作用知道吗?

7、 kafka 如何保证消息的消费顺序?

8、 kafka 如何保证消息不丢失?

9、 kafka 判断一个节点是否还活着有哪两个条件?

10、 producer 是否直接将数据发送到 broker leader (主节点)?

11、 kafka consumer 是否可以消费指定分区消息吗?

12、 kafka 高效文件存储设计的特点是什么?

13、 partition 的数据如何保存到硬盘?

14、 kafka 生产数据时数据的分组策略是怎样的?

15、 consumer 是推还是拉?

16、 kafka 维护消费状态跟踪的方法有什么?

二、详情解读:

1、kafka 是什么?主要应用场景有哪些?

kafka 是一个分布式流式处理平台 。流平台具有三个关键功能:

  • 消息队列 :发布和订阅消息流,这个功能类似于消息队列,这也是 kafka 也被消息队列的原因。


  • 容错的持久方式存储记录消息流 kafka 会把消息持久化到磁盘上,有效避免了消息丢失的风险。


  • 流式处理平台 :在消息发布的时候进行处理, kafka 提供了一个完整的流式处理类库。


kafka 主要有 两大应用场景

  • 消息队列 :建立实时流数据管道,以可靠地在系统或应用程序之间获取数据。


  • 数据处理 :构建实时的流数据处理程序来转换或处理数据流。

2、和其他消息队列相比、kafka 的优势在哪里?

我们现在经常提到 kafka 的时候就已经默认它是一个非常优秀的消息队列了,我们也会经常拿它跟 rocketMQ、rabbitMQ 对比


我觉得 kafka 相比其他消息队列 主要的优势 如下:

  • 极致的性能 :基于 scala java 语言开发,设计中大量使用了批量处理和异步的思想,最高可以每秒处理千万级别的消息。


  • 生态系统兼容性无可匹敌 kafka 与周边生态系统的兼容性是最好的没有之一,尤其在大数据和流计算领域。


实际上在早期的时候 kafka 并不是一个合格的消息队列,早期的 kafka 在消息队列领域就像是一个衣衫褴褛的孩子一样,功能不完备并且有一些小问题,比如丢失消息、不保证消息可靠性等等。


当然,这也和 LinkedIn 最早开发 kafka 用于处理海量的日志有很大关系,人家本来最开始就不是为了作为消息队列的,谁知道后面误打误撞在消息队列领域占据了一席之地。

3、什么是 producer、consumer、broker、topic、partition?

kafka 将生产者发布的消息发送到 topic (主题)中,需要这些消息的消费者可以订阅这些 topic (主题)。 kafka 比较重要的几个概念:


  • producer (生产者):产生消息的一方。
  • consumer (消费者):消费消息的一方。
  • broker (代理):可以看作是一个独立的 kafka 实例。多个 kafka broker 组成一个 kafka cluster
  • topic (主题): producer 将消息发送到特定的主题, consumer 通过订阅特定的 topic (主题)来消费消息。
  • partition (分区):partition 属于 topic 的一部分。一个 topic 可以有多个 partition,并且同一 topic 下的 partition 可以分布在不同的 broker 上,这也就表明一个 topic 可以横跨多个 broker

4、kafka 多副本机制了解吗?

kafka 为分区 partition (引入了多副本( replica )机制。分区( partition )中的多个副本之间会有一个叫做 leader 的家伙,其他副本称为 follower


我们发送的消息会被发送到 leader 副本,然后 follower 副本才能从 leader 副本中摘取消息进行同步。


生产者和消费者只与 leader 副本交互。你可以理解为其他副本只是 leader 副本的拷贝,它们的存在只是为了保证消息存储的安全性。


leader 副本发生故障时会从 follower 中选举出一个 leader ,但是 follower 中如果有和 leader 同步程序达不到要求的参加不了 leader 的竞选。

5、kafka 多分区(partition)以及多副本(replica)机制有什么好处呢?

  • kafka 通过给特定 topic 指定多个 partition , 而各个 partition 可以分布在不同的 broker 上,这样便能提供比较好的并发能力(负载均衡)。


  • partition 可以指定对应的 replica 数,这也极大地提高了消息存储的安全性,提高了容灾能力,不过也相应的增加了所需要的存储空间。

6、zookeeper 在kafka 中的作用知道吗?

  • broker 注册 :在 zookeeper 上会 有一个专门用来进行 broker 服务器列表记录的节点。每个 broker 在启动时,都会到 zookeeper 上进行注册,即到 /brokers/ids 下创建属于自己的节点。每个 broker 就会将自己的 IP 地址和端口等信息记录到该节点中去。


  • topic 注册 :在 kafka 中, 同一个 topic 的消息会被分成多个分区并将其分布在多个 broker 上,这些分区信息以及与 broker 的对应关系也都是由 zookeeper 在维护。比如我创建了一个名字为 my-topic 的主题并且它有两个分区,对应到 zookeeper 中会创建这些文件夹: /brokers/topics/my-topic/partitions/0、/brokers/topics/my-topic/partitions/1


  • 负载均衡 :上面也说过了 kafka 通过给特定 topic 指定 多个 partition ,而各个 partition 可以分布在不同的 partition kafka 会尽力将这些 partition 分布到不同的 broker 服务器上。当生产者产生消息后也会尽量投递到不同 broker partition 里面。当 consumer 消费的时候, zookeeper 可以根据当前的 partition 数量以及 consumer 数量来实现动态负载均衡。

7、kafka 如何保证消息的消费顺序?

我们在使用消息队列的过程中经常有业务场景需要严格保证消息的消费顺序,比如我们同时发了 2 个消息,这 2 个消息对应的操作分别对应的数据库操作是:


  • 更改用户会员等级。
  • 根据会员等级计算订单价格。


假如这两条消息的消费顺序不一样造成的最终结果就会截然不同。

kafka partition (分区)是真正保存消息的地方,我们发送的消息都被放在了这里。而我们的 partition (分区)又存在于 topic (主题)这个概念中,并且我们可以给特定 topic 指定多个 partition


每次添加消息到 Partition (分区)的时候,都会采用尾加法, kafka 只能为我们保证 partition (分区)中的消息有序。


消息在被追加到 partition (分区)的时候都会分配一个 特定的偏移量 offset )。 kafka 通过偏移量( offset )来保证消息在分区内的顺序性。


所以,我们就有一个很简单的保证消息顺序的方法: 1 topic 只对应一个 partition 。这样当然可以解决问题,但是破坏了 kafka 的设计初衷。


kafka 中发送 1 条消息的时候,可以指定 topic,partition, key,data (数据) 4 个参数。如果你发送消息的时候指定了 Partition 的话,所有消息都会被发送到指定的 Partition


并且,同一个 key 的消息可以保证只发送到同一个 partition ,这个我们可以采用表/对象的 id 来作为 key


总结一下,对于如何保证 Kafka 中消息消费的顺序,有了下面两种方法:

  • 1 Topic 只对应一个 Partition
  • 发送消息的时候指定 key/Partition

8、kafka 如何保证消息不丢失?

生产者丢失消息的情况:

生产者( Producer ) 调用 send 方法发送消息之后,消息可能因为网络问题并没有发送过去。


所以,我们不能默认在调用 send 方法发送消息之后消息发送成功了。为了确定消息是发送成功,我们要判断消息发送的结果。


但是要注意的是 Kafka 生产者( Producer ) 使用 send 方法发送消息实际上是异步的操作,我们可以通过 get() 方法获取调用结果,但是这样也让它变为了同步操作。


消费者丢失消息的情况

我们知道消息在被追加到 Partition (分区)的时候都会分配一个特定的偏移量( offset )。偏移量( offset )表示 Consumer 当前消费到的 Partition (分区)的所在的位置。

Kafka 通过偏移量( offset )可以保证消息在分区内的顺序性。


当消费者拉取到了分区的某个消息之后,消费者会自动提交了 offset


自动提交的话会有一个问题,试想一下,当消费者刚拿到这个消息准备进行真正消费的时候,突然挂掉了,消息实际上并没有被消费,但是 offset 却被自动提交了。


解决办法也比较粗暴,我们手动关闭自动提交 offset ,每次在真正消费完消息之后再自己手动提交 offset


但是,细心的朋友一定会发现,这样会带来消息被重新消费的问题。比如你刚刚消费完消息之后,还没提交 offset ,结果自己挂掉了,那么这个消息理论上就会被消费两次。

9、kafka 判断一个节点是否还活着有哪两个条件?

  • 节点必须可以维护和 ZooKeeper 的连接, Zookeeper 通过 心跳机制 检查每个节点的连接;
  • 如果节点是个 follower ,他必须能及时的同步 leader 的写操作,延时不能太久。

10、producer 是否直接将数据发送到 broker 的 leader(主节点)?

producer 直接将数据发送到 broker leader (主节点),不需要在多个节点进行分发,为了

帮助 producer 做到这点,


所有的 Kafka 节点都可以及时地告知:哪些节点是活动的,目标 topic 目标分区的 leader 在哪。这样 producer 就可以直接将消息发送到目的地了。

11、kafka consumer 是否可以消费指定分区消息吗?

Kafa consumer 消费消息时,向 broker 发出” fetch “请求去消费特定分区的消息, consumer 指定消息在日志中的偏移量( offset ),就可以消费从这个位置开始的消息, customer 拥有了 offset 的控制权,可以向后回滚去重新消费之前的消息,这是很有意义的。

12、kafka 高效文件存储设计的特点是什么?

  • Kafka topic 中一个 partition 大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。
  • 通过索引信息可以快速定位 message 和确定 response 的最大大小。
  • 通过 index 元数据全部映射到 memory ,可以避免 segment file IO 磁盘操作。
  • 通过索引文件稀疏存储,可以大幅度降低 index 文件元数据占用空间大小。

13、partition 的数据如何保存到硬盘?

topic 中的多个 partition 以文件夹的形式保存到 broker ,每个分区序号从 0 递增,且消息有序。


Partition 文件下有多个 segment(xxx.index,xxx.log)


segment 文件里的 大小和配置文件大小一致可以根据要求修改,默认为 1g 。如果大小大于 1g 时,会滚动一个新的 segment 并且以上一个 segment 最后一条消息的偏移量命名。

14、kafka 生产数据时数据的分组策略是怎样的?

生产者决定数据产生到集群的哪个 partition 中,每一条消息都是以( key value )格式, Key 是由生产者发送数据传入,所以生产者( key )决定了数据产生到集群的哪个 partition

15、consumer 是推还是拉?

customer 应该从 brokes 拉取消息还是 brokers 将消息推送到 consumer ,也就是 pull push


在这方面, Kafka 遵循了一种大部分消息系统共同的传统的设计: producer 将消息推送到 broker consumer broker 拉取消息。


push 模式,将消息推送到下游的 consumer 。这样做有好处也有坏处:由 broker 决定消息推送的速率,对于不同消费速率的 consumer 就不太好处理了。


消息系统都致力于让 consumer 以最大的速率最快速的消费消息,但不幸的是, push 模式下,当 broker 推送的速率远大于 consumer 消费的速率时, consumer 恐怕就要崩溃了。


最终 Kafka 还是选取了传统的 pull 模式。

16、kafka 维护消费状态跟踪的方法有什么?

大部分消息系统在 broker 端的维护消息被消费的记录:一个消息被分发到 consumer broker 就马上进行标记或者等待 customer 的通知后进行标记。这样也可以在消息消费后立马就删除以减少空间占用。

Golang 消息队列面试题与答案