监控工具

kafka eagle 也是非常不错的监控软件,好像也是国人写的,一直在更新,而且不比kafka manager差


kafka manager

kafka-manager最近的演进速度不及Kafka本身。目前我了解到用的比较多的是 JMXTrans + InfluxDB + Grafana这种组合

Kafka 那些情况下耗 CPU

是因为通常情况下Kafka不太占用CPU,因此没有这方面的最佳实践出来。但有些情况下Kafka broker是很耗CPU的:

  1. server和client使用了不同的压缩算法;
  2. server和 client版本不一致造成消息格式转换;
  3. broker端解压缩校验

kafka如何做压力测试,它的参考主要指标是什么,比如QPS,最大连接数,延迟等等

  1. Kafka提供了命令行脚本可以执行producer和consumer的性能测试,主要指标还是 TPS,延时

扩容如何做到平滑扩容,不影响原业务

增加broker很简单,也不会对现有业务有影响。关键是做好迁移计划——比如避开业务高峰时 刻,如果迁移对业务影响最小


感觉kafka和rocketmq的设计有很多相似之处,能否列举一下他们之间的区别呢?如果要选型,哪些场景适合用kafka,哪些场景适合用rocketmq呢?

说实话不敢妄言两者的优劣,网上也有一些文章比较过两者的区别。就目前公开的资料查看,RocketMQ宣称擅长主打金融业务领域场景,我个人是比较相信的。Kafka更多还是发家于大数据领域。


提到了消息的协议,介绍了两种模式一种是点对点,一种是订阅\发布模式。为什么我一开始想到消息的协议是http之类的传输协议?这两个有什么区别和联系?

http不属于消息传输协议,它是网络通信协议的一种,严格来说这是两个范畴或者说是两个层次上的协议。 通常来说,两个进程进行数据流交互的方式一般有三种:

  1. 通过数据库:进程1写入数据库;进程2读取数据库
  2. 通过服务调用:比如REST或RPC,而HTTP协议通常就作为REST方式的底层通讯协议
  3. 通过消息传递的方式:进程1发送消息给名为broker的中间件,然后进程2从该broker中读取消 息。消息传输协议属于这种模式 因此我说虽然我们都称它们为协议,但它们不是一个层次上的协议。


kafka,怎么解决实时结果响应问题呢?比如秒杀商品,生产者产生订单,消费者处理订单结果,那这结果如何实时返回给用户呢?

这个场景使用Kafka Streams比较适合,它就是为read-process-write场景服务的


想问下有些业务用mq来做异步处理,为了削峰填谷,是不是上游发送消息成功就认为业务成功了,可能下游过很久去消费,那实时性要求很高的业务怎么办呢,比如生成了订单但是一直不处理也不好吧。mq和rpc调用的区别是什么呢?

mq和rpc的区别往大了说属于数据流模式(dataflow mode)的问题。 我们常见的数据 流有三种:1. 通过数据库;2. 通过服务调用(REST/RPC); 3. 通过异步消息传递(消息引擎,如 Kafka) RPC和MQ是有相似之处的,毕竟我们远程调用一个服务也可以看做是一个事件,但不同之处在于:

  1. MQ有自己的buffer,能够对抗过载(overloaded)和不可用场景
  2. MQ支持重试
  3. 允许发布/订阅模式 当然它们还有其他区别。应该这样说RPC是介于通过数据库和通过MQ之间的数据流模式。


请思考一下为什么 Kafka 不像 MySQL 那样允许追随者副本对外提供读服务?

知乎问答

**如果允许follower副本对外提供读服务(主写从读),首先会存在数据一致性的问题,消息从主节点同步到从节点需要时间,可能造成主从节点的数据不一致。主写从读无非就是为了减轻leader节点的压力,将读请求的负载均衡到follower节点,如果Kafka的分区相对均匀地分散到各个broker上,同样可以达到负载均衡的效果,没必要刻意实现主写从读增加代码实现的复杂程度

首先明确一下:主从分离与否没有绝对的优劣,它仅仅是一种架构设计,各自有适用的场景。 第二、如你所说,Redis和MySQL都支持主从读写分离,我个人觉得这和它们的使用场景有关。对于那种读操作很多而写操作相对不频繁的负载类型而言,采用读写分离是非常不错的方案——我们可以添加很多follower横向扩展,提升读操作性能。反观Kafka,它的主要场景还是在消息引擎而不是以数据存储的方式对外提供读服务,通常涉及频繁地生产消息和消费消息,这不属于典型的读多写少场景,因此读写分离方案在这个场景下并不太适合。 第三、Kafka副本机制使用的是异步消息拉取,因此存在leader和follower之间的不一致性。如果要采用读写分离,必然要处理副本lag引入的一致性问题,比如如何实现read-your-writes、如何保证单调读(monotonic reads)以及处理消息因果顺序颠倒的问题。相反地,如果不采用读写分离,所有客户端读写请求都只在Leader上处理也就没有这些问题了——当然最后全局消息顺序颠倒的问题在Kafka中依然存在,常见的解决办法是使用单分区,其他的方案还有version vector,但是目前Kafka没有提供。 最后、社区正在考虑引入适度的读写分离方案,比如允许某些指定的follower副本(主要是为了考虑地理相近性)可以对外提供读服务。当然目前这个方案还在讨论中。

因为mysql一般部署在不同的机器上一台机器读写会遇到瓶颈,Kafka中的领导者副本 一般均匀分布在不同的broker中,已经起到了负载的作用

kafka是按照什么规则将消息划分到各个分区的?

如果producer指定了要发送的目标分区,消息自然是去到那个分区;否则就按照producer端参数partitioner.class指定的分区策略来定;如果你没有指定过partitioner.class,那么默认的规则是:看消息是否有key,如果有则计算key的murmur2哈希值%topic分区数;如果没有key,按照轮询的方式确定分区。

既然同一个topic下的消息分布在不同的分区,那是什么机制将topic、partition、record关联或者说管理起来的?


这个层级其实是逻辑概念。在物理上还是以日志段(log segment)文件的方式保存,日志段 文件在内存中有对应的Java对象,里面关联了你说的这些。

kafka能否做到多个消费者消费一个生产者生产的数据,并能保证每个消费者消费的消息不会重复,做到并行消费?

Kafka提供了消费者组实现你说的这个需求

每个消费者有着自己的消费者位移。“重平衡”时Kafka怎么知道已挂的消费者消费到哪里了?

重平衡时每个消费者都会尽力去做一次位移提交(如果它会提交位移的话),这样当rebalance完成后Kafka会告诉它们订阅分区当前消费到了那里。

Leader-Follower 指的是副本之间的关系,broker之间是对等关系,对吧?如果是对等关系,生产和消费时我怎么找到领导者副本所在的broker呢?

客户端会首先请求topic分区的leader副本在哪个broker上,内部自动执行的

服务端Consumer的TotalTimeMs的值有时候好几万,有遇到过吗?这种情况引发的原因是什么呀?

好几万大概对应于几十秒,TotalTimeMs是指请求从接收到处理完成后发送响应的间隔。这中间包含很多环节,你最好确认下时间都花在哪里了? 比如请求入队列的时间、本地读磁盘时间、等待远程API调用的时间(由于你是consumer,这个应该没有)、响应入队列时间、以及response发送时间。


通过spingboot使用非注解方式配置kafka消费者,每一段时间会出 (Re-)joining group的情况,导致即便少量消息也会堆积直到消费者挂上,出现这种情况的原因大概会有哪些呢?

  1. 查看一下你的程序中是否频繁创建KafkaConsumer实例;
  2. 查看一下你的消息平均处理时间是否超过10分钟

我在使用Kafka中,出现消息阻塞不消费的问题,换了消费组之后过段时间又不消费

了,不知什么原因

两个可能的原因,①就是没有新消息可供消费了,②某天消息格式有问题导致解析不了 了,不过这种情况很罕见,一般是因为网络传输出问题导致

advertised.listeners 这个配置能否再解释一下。感觉配置了 listeners之后就不用配置这个了呀?


advertised.listeners主要是为外网访问用的。如 果clients在内网环境访问Kafka不需要配置这个参数。 常见的玩法是:你的Kafka Broker机器上配置了双网卡,一 块网卡用于内网访问(即我们常说的内网IP);另一个块用 于外网访问。那么你可以配置listeners为内网IP, advertised.listeners为外网IP。

假如现有集群已经有3个

分区,动态添加两个分区, 原有的分区会迁移数据到新增 的分区吗?

不会。已有数据将一直“躺在”原有分区中。

在消息重试的时候,分区策略会重新再计算一次

吗?比如一开始选择到5号分区,但是5号分区有问题导致 重试,重试的时候可以重试发送到别的分区上吗?

不会的。消息重试只是简单地将消息重新发送到 之前的分区

广州机房怎么消费广州partition的数据,consumer如何

指定消费的partition。

使用这个方法:consumer.assign()直接消息指定 分区

partition的个数是从哪配置的呢

topic创建的时候指定了分区数

两个跨区域的集群zookeeper放在那个城市呢?广州

还是北京?还有就是能否使用多topic?比如广州一个 topic北京一个topic。还有这样做和您建议的分区方式比 有什么优劣性的不同呢?

Zk集群没有一定要放在哪个城市。这个例子只是 配合分区策略引出的,而且的确也有大厂这么使用。其实更 好的做法还是多集群的方式。每个IDC有自己的Kafka集 群,彼此同步。至于多topic的方式如果业务分割得清晰实 际上是更好的解决方案:)

对消息层次、消息集合、消息、日志项这些概念与它们之间的关系感觉很懵,

消息层次都分消息集合以及消息,消息集合中包含日志项,日志项中封装消息, 那么日志项中封装的是producer发送的消息吗? 一个日志项中会包含多条消息吗? 消息集合中消息项封装的的消息与消息层次包含的消息有什么关系呢?

消息批次RecordBatch里面包含若干条消息(record)。 你可以认为消息批次和消息集合是等价的,消息和日志项是等价的。 这样消息层次有两层:外层是消息批次(或消息集合);里层是消息(或日志项)。 Producer以recordbatch为单位发送消息,对于V2版本一个batch中通常包含多条消息。 在V2版本中,在batch层面计算CRC值;在V1版本中,每条消息都要计算CRC值。

producer.send(msg, callback)中callback主要用来做什么?可以用来重新发送数据么?如

果可以的话,跟producer的配置retries是不是功能重复了

可以。retries是producer自动帮你重试。callback中你可以做一些处理之后再重试

在“producer.send(msg, callback)的callback方法中重试,和设置retries参数重试,会不

会冲突?2个都设置以哪个为准?

不冲突。对于可重试的错误,retries才会触发,否则直接 进入到callback

设置 acks = all。表明所有副本 Broker 都要接收到消息,该消息才算是“已提交”。如果

所有的Broker都要收到消息才能算作已提交,会不会对系统的吞吐量影响很大?另外这里 的副本指的是不是仅仅是ISR?

就我碰到的实际场景,影响还是很大的。acks=all时,大部分的请求处理延时都花在了 follower同步上。 是的,acks=all表明所有ISR中的副本都要同步。

消费组中的消费者个数如果超过topic的分区数,就会有

消费者消费不到数据。但如果是同一个消费组里的两个消 费者通过assign方法订阅了同一个TopicPartition,是不 是会有一个消费者不能消费到消息?

: 如果使用assign,则表明该consumer是独立 consumer(standalone consumer),它不属于任何消费 者组。独立consumer可以订阅任何分区,彼此之间也没有 关系,即两个独立consumer可以订阅并消费相同的分区

近集群扩容,需要对

__consumer_offset这个topic进行reassign,请问有没有 坑啊?需要注意哪些事项呢?

reassign操作很容易出错,不只是对 __consumer_offsets。我个人的建议哈:1. 业务低峰时段 做;2. 不要topic级别整体迁移,最好按照分区级别来做。 比如一次迁移几个分区这样

具体是从哪个版本开始,位移数据开始默认的不存在zk而是存在自己内部了?

1.0.9

什么场景下适合使用自动提交位移?

不在乎重复消费

单个消费实例,单个partion,消费者消费失败,

offset可以重新回到前面位置重新消费吗?

消费者重启回来后会从最新一次提交的位移处继续消费

前几年一直有个说法,说kafka不适合创建过多topic,请问现在的新版还有这个

问题么?

topic过多其实是指分区数过多。会有两个可能的问题:

  1. controller无法管理这么多分 区;
  2. 分区数过多导致broker物理随机IO增加,减少吞吐量。

第一个问题社区算是修复了吧,目前单controller能够支持20w的分区数,况且社区也在考虑做多 controller方案;第二个问题目前没有太多直接的修复举措,只能说具体问题具体分析吧

在consumer提交位移的时候,往所在的broker写消息,那如果当前的

broker挂掉了,写入位移主题的消息会丢失吗?还是说位移主题在写入的时候也会把消息 同步到其他broker中的副本中,从而保证写入消息不丢失呢

不会。位移主题的failover和高可用管理和普通Kafka topic是一样的。也会执行leader 选举。

offset topic是在coordinator对应的broker上创建且只创建一次是么?

offset topic在整个集群上被创建出来,并且只会创建一次

consumer 是如何从这个位移主题中拿到曾经属于自己组的offset呢?

首先找到对应的Coordinator,Coordinator保存了这些数据,然后consumer向 Coordinator发送请求去请求这些数据

关闭unclean后,有哪些方法可以保证available啊?

增加副本数

如果某一个副本所在的broker挂了,kafka会在另一个broker上面新创建一个partition

来补充吗?

不会

如果这三个副本所在的broker都挂了,那kafka会不会在一个新的broker上面重新创建

一个新的partition来支持读写,还是说,这个partition就不在工作了?

不工作了

kafka新增一块磁盘,如何做到数据迁移到新盘上。是这样的,之前磁盘只有一

块,用久了磁盘忙了,修改保留数据时间已经不能支撑业务了。于是在不重启机器的情况 下,新增了一块盘,然后重启kafka,发现新盘没有数据进来。请问要如何做,可以把数据 迁移到新盘上

使用kafka-reassign-partitions脚本可以,具体用法看一下—reassignment-json-file