Java面试问题汇总(消息队列)

14.消息队列

《深入理解Kafka 核心设计与实践原理》

Kafka

说一下Kafka

Kafka是一款高性能的消息中间件,包括Producer,Consumer,Broker,以及Zookeeper,Zookeeper用来负责集群元数据管理,控制器的选举等操作,Producer将消息发送到Broker,由Broker负责将收到的消息存储到磁盘中,Consumer负责从Broker订阅并消费消息。Kafka中的消息是以主题为单位,主题可以分布在不同的分区,分区可以分布于不同的Broker,分区有Leader 与副本follower,follower负责从leader同步数据,leader负责读写请求

消息的幂等性处理思路

主要是防止消息重复消费,通过业务方去保证消息的幂等性,每条消息设置一个唯一Id,数据库的话通过唯一索引。

消息队列如何保证高可用

kafka可以有多个Borker,一个topic会将数据存储在不同的partiton上, 并且有多个副本来同步数据,但只会有一个leader,数据以Log的形式存储在硬盘中,并且记录了消费的offset。如果leader挂掉,会从ISR集合中的副本选出一个做为leader。

Kafka 新建的分区会在哪个目录下创建

在启动Kafka集群之前,我们需要配置好log.dirs参数,其值是kafka数据的存放目录,这个参数可以配置多个目录,目录之间使用逗号分隔,通常这些目录是分布在不同的磁盘上用于提高读写性能。

也可以配置log.dir参数,含义一样,只需要设置其中一个即可。如果log.dirs参数只配置了一个目录,那么分配到各个Broker上的分区肯定只能在这个目录下创建文件夹用于存储数据。

但是如果log.dirs参数配置了多个目录,Kafka会在含有分区目录最少的文件夹中创建新的分区目录,分区目录名为Topic名 + 分区ID。注意,是分区文件夹总数最少的目录,而不是磁盘使用量最少的目录

Kafka的 ack 机制

ack 有三个值 0 1 -1

0 : 生产者不会等待borker返回,延迟最低但是存储的保证最弱当server挂掉的时候就会丢数据

1 : 等待leader确认消息返回,但如果Leader挂掉后不保证是否复制完成

-1: 等待所有的副本确认消息返回

如何保证消息可靠性

kafka保证消息可靠性,可以通过如下几个配置:

  1. 生产者配置 acks = all (-1) ISR中的所有副本都写入成功,才代表该消息发送成功
  2. min.insync.replicas默认为1,指定了ISR集合中最小的副本数,不满足条件就会抛出NotEnoughReplicasException 或 NotEnoughReplicasAfterAppendException,也就是必须保证有一个副本同步数据跟得上leader
  3. unclean.leader.election.enable 默认为false, 当leader下线的时候可以从非ISR集合中选举新的leader,这样能提高可用性,但会丢数据
  4. 配置log.flush.interval.messages 和 log.flush.interval.ms 同步刷盘策略
  5. 消费端手动提交位移,enable.auto.commit 设置为false,自动提交会带来重复消费和消息丢失的问题,客户端如果消息消费失败应该放入死信队列,以便后期排除故障
  6. 回溯消费功能,消息貌似已经成功消费,但实际消息失败了,不知道是什么错误造成的,就可以通过回溯消费补偿,或者复现 “丢失”,seek()方法

消息积压问题

如果消息积压了太多,一直消费不了,需要检查是不是consumer有问题,或者服务端磁盘是否快满了。

  1. consumer有问题就修复问题。但由于积压的数据太多,用原程序消费还是太慢。就需要扩容,新建临时topic,将分区改为原来的10倍,写程序将原来积压的消息发送到新建的topic中,启动10倍的机器来消费这些数据
  2. 服务端磁盘满,就只能扩容服务端磁盘,再采用第一种办法来修复问题

kafka的分区策略

消费者客户端参数partition.assignment.strategy 来配置消费分区策略

  1. RangeAssignor 默认分配策略 通过 分区数/消费者总数 来获得一个跨度进行分配
  2. RoundRobinAssignor 轮询分配策略
  3. StickyAssignor 能够使分区的分配尽可能与上一次保持一致,避免过度重分配
  4. 自定义分配,实现PartitionAssignor接口

你可能感兴趣的:(java)