Java面试之kafka

154 阅读6分钟

Kafka

1.kafka为什么不基于内存?

答:因为kafka是基于scala和java实现的。需要运行在jvm中,如果是基于内存实现,会在堆中进行大量数据读写,会频繁 full gc。

 

2.kafka为什么快

答:1.顺序读写:省去了大量磁头寻址的时间。

2.0拷贝:减少不必要的拷贝次数

3.mmap:  将磁盘文件映射到内存,通过修改内存即可以修改磁盘文件

      问题:不可靠,因为写到mmap的数据并没有真正写到磁盘上,需要程序主动flush才能写入

3.kakfa如何保证消息 不丢失?

答 1.生产者丢失  网络问题没有发送成功

   解决:判断消息发送的回调结果。引入重试机制。

   

   2.消费者丢失   消费者拿到消息还没消费,挂掉了,然后offset自动提交

   解决:关闭自动提交,消息消费完再手动提交   

   引发问题:消息可能重复消费

    

   3.kakfa自身丢失  leader所在的broker挂掉。但是数据没有被follower同步

   解决:设置acks=all   表示所有副本都要接收到该消息才算成功。

 

扩展: acks=1 表示消息被leader接收计算成功

 

4.kafka 消息保证不重复消费?

 

解决

(1)、可在内存中维护一个set,只要从消息队列里面获取到一个消息,先查询这个消息在不在set里面,如果在表示已消费过,直接丢弃;如果不在,则在消费后将其加入set当中。

(2)、如何要写数据库,可以拿唯一键先去数据库查询一下,如果不存在在写,如果存在直接更新或者丢弃消息。

(3)、如果是写redis那没有问题,每次都是set,天然的幂等性。

(4)、让生产者发送消息时,每条消息加一个全局的唯一id,然后消费时,将该id保存到redis里面。消费时先去redis里面查一下有么有,没有再消费。

(5)、数据库操作可以设置唯一键,防止重复数据的插入,这样插入只会报错而不会插入重复数据。

5.kafka如何保证消费顺序?

解决:1.每一个topic只有一个分区

       2.发送消息时指定分区\

6.kakfa的leader和foller 如何同步数据?

答:kafka的复制机制既不是完全的同步复制,也不是单纯异步复制。完全同步复制要求all live follow都复制完,这条消息才被认为commit。非常影响吞吐率。而异步复制,数据只要被leader写入log则认为已经commit,如果leader挂掉了的话,容易造成数据丢失。kafka的ISR机制很好的均衡了确保数据不丢失以及吞吐率。follow可以批量的从leader复制数据,而且leader充分利用了磁盘的顺序读写以及sendfile机制,极大的提高了复制性能,内部批量写磁盘,大大减少了follow和leader的信息量差。

 

7.消息积压怎么解决

 1.扩容消费端。2.优化业务逻辑,提高消费能力。

8.ISR机制

ISR就是kafka某个分区中维护的同步集合,该集合就是ISR。每一个partitino都有一个ISR,它是由leader动态维护。只要处于ISR集合中的副本,就意味着follower副本和leader副本保持同步状态,同时也只有处于ISR集合中的副本才能被选举为leader

kafka的Replica

  1. kafka的topic可以设置N个副本(replica),副本数最好小于broker数量,其实一般就是一个broker最多一个replica,可以用broker id指定partition replica。
  2. 创建副本的单位是topic的分区,每个分区有一个leader和0到多个follower,我们把多个replica分为leader replica和follower replica。
  3. 当producer在向partition中写数据时,根据ack机制,默认为ack=1,只会leader中写入数据,然后leader中的数据会复制到其他的replica中,follower会周期性的从leader中pull数据,但是对于数据的读写操作都在leader replica中,follower副本只有当leader副本挂掉之后才重新选去leader,follower并不向外提供服务。

9.ack机制

我们知道如果需要往kafka里面发送消息,需要producer完成,那么我们怎么保证消息是否发送成功呢。kafka提供了消息确认机制。也就是说我们通过配置来决定发送到对应分区的几个副本就算成功。我们可以通过配置acks参数指定。

  • acks = 0,意味着producer发送消息出去就认为发送成功。但是这种也非常容易丢失数据,比如发送的对象无能被序列化或者网卡发生故障等。

  • acks = 1,意味着leader收到消息并写入分区数据文件返回成功消息则认为发送成功。在这个模式下,如果发生正常的 Leader 选举,生产者会在选举时收到一个 LeaderNotAvailableException 异常,如果生产者能恰当地处理这个错误,它会重试发送悄息,最终消息会安全到达新的 Leader 那里。不过这个模式也可能会丢失数据,就是当leader写好后,在复制到follower副本之前leader崩溃了。

  • acks = -1,意味着 Leader 在返回确认或错误响应之前,会等待所有同步副本都收到悄息。如果和 min.insync.replicas 参数结合起来,就可以决定在返回确认前至少有多少个副本能够收到悄息,生产者会一直重试直到消息被成功提交。不过这个非常慢,因为生产者需要等待所有副本消息才能继续发消息。

10.集群部署

kafka linux 集群部署

1.修改 config/service.properties

broker.id 每个kafka必须唯一

advertised.listeners=PLAINTEXT://+ 当前服务器ip 端口

zookeeper.connect 集群zookeeper地址

-kafka 运行日志存放路径

log.dirs=/usr/local/kafka_2.12-2.2.2/log/kafka

-topic 在当前broker上的分片个数,与broker保持一致

num.partitions=3

2.修改 zookeeper.properties

目录必须存在 不存在要手动建文件夹

#修改为自定义的zookeeper数据目录

dataDir=/usr/local/kafka_2.12-2.2.2/zookeeper

#修改为自定义的zookeeper日志目录

dataLogDir=/usr/local/kafka_2.12-2.2.2/log/zookeeper 

#注释掉

#maxClientCnxns=0

#设置连接参数,添加如下配置

tickTime=2000    #为zk的基本时间单元,毫秒

initLimit=10     #Leader-Follower初始通信时限 tickTime*10

syncLimit=5     #Leader-Follower同步通信时限 tickTime*5

#设置broker Id的服务地址

server.0=172.27.178.79:2888:3888

server.1=172.27.178.80:2888:3888

server.2=172.27.178.81:2888:3888

在kafka_2.12-2.2.2 目录下新建文件夹 zookeeper

跳转 zookeeper 目录,执行 echo 0 > myid,其中 0 为本服务器kafka broker.id

3.启动zookeeper

分别在各个服务器启动zookeeper

跳转到kafka 目录

cd /home/app/kafka_2.12-2.2.2

nohup ./bin/zookeeper-server-start.sh ./config/zookeeper.properties > ./log/zookeeper/zookeeper.log 2>1 &

4.启动kafka

待zookeeper启动完成,依次在各服务器启动kafka

跳转到kafka 目录

cd /home/app/kafka_2.12-2.2.2

 nohup ./bin/kafka-server-start.sh ./config/server.properties > ./log/kafka/kafka.log 2>1 &

5.验证安装是否成功

跳转kafka目录

cd /home/app/kafka_2.12-2.2.2

在某台服务器上创建话题

./bin/kafka-topics.sh -create --zookeeper 

172.27.178.79:2181,172.27.178.80:2181,172.27.178.81:2181 -replication-factor 3 --partitions 3 --topic test

在某台服务器上创建生产者

  ./bin/kafka-console-producer.sh --broker-list 172.27.178.79:9092,172.27.178.80:9092,172.27.178.81:9092 --topic test

  在其他服务器上创建消费者

./bin/kafka-console-consumer.sh --bootstrap-server 172.27.178.79:8092,172.27.178.80:8092,172.27.178.81:9092 --topic test11 -- from-geginning

在生产者上发送消息,看消费者服务器是否能接收

6.关闭kafka

ps -ef | grep kafka

关闭所有kafka 进程 每个服务器有四个进程