消息堆积可能原因如下:1. 生产速度大于消费速度,这样可以适当增加分区,增加consumer数量,提升消费TPS;2. consumer消费性能低,查一下是否有很重的消费逻辑(比如拿到消息后写HDFS或HBASE这种逻辑就挺重的),看看是否可以优化consumer TPS;3. 确保consumer端没有因为异常而导致消费hang住; 4. 如果你使用的是消费者组,确保没有频繁地发生rebalance
实际上这个交由OS来决定,Kafka不管
从拉取的方式。Kafka定义了水位的概念来标识拉取的进度
新增加了分区之后consumer和producer不会立即感知,通常可能会等待一段时间。如果producer先感知到了并向新分区发送消息,那么consumer后感知到之后直接从最新位移开始读取消息,那么之前发送的消息就不会被消费了
影响还是很大的。acks=all时,大部分的请求处理延时都花在了follower同步上。
是的,acks=all表明所有ISR中的副本都要同步。
min.insync.replicas是保证下限的。acks=all的含义是producer会等ISR中所有副本都写入成功才返回,但如果不设置min.insync.replicas = 5,默认是1,那么假设ISR中只有1个副本,只要写入这个副本成功producer也算其正常写入,因此min.insync.replicas保证的写入副本的下限。
根据默认分区策略,同一个key的消息肯定会发送到同一个分区
首先,你的消息会被发送到某个分区的leader副本上。这个分区的leader副本只能存在于3个broker中的一个,但是如果test的副本数是那么一条消息也会被备份到其他两个broker上。只是只有leader副本对外提供服务,因此没有顺序乱的情况出现。
如果想保证顺序,指定消息key即可,这样能保证分送到同一个分区上。是否发到同一个broker上无关紧要
kafka-topics支持在创建topic时指定partition放在那些broker上
感觉没什么区别,只是缓存中的微弱区别罢了。
通常1台broker上有多个分区依然能提升TPS,毕竟单个分区消耗不掉大部分的系统资源。当然一切以实际测试结果为准。
使用这个方法:consumer.assign()直接消息指定分区
"分区的各个副本是怎样在节点上分布的" --- 如果不考虑机架信息的话,你基本上可以认为是轮询的分配方案,新分区的副本的分布也是相同的原理。
多个producer发送的消息彼此之间没有前后顺序之分。谁在谁前面都是可能的,上面的情况是有可能的
Producer发送消息的时候可以直接指定key,比如producer.send(new ProducerRecord("my-topic", "key", "value"));
同一个分区的不同副本可能分布在不同的机器上
1是,一个生产者,发两次消息,但是网络原因,消息到达的顺序和消息发送的顺序不一致,
防止乱序可以通过设置max.in.flight.requests.per.connection=1来保证
max.in.flight.requests.per.connection = 1 限制客户端在单个连接上能够发送的未响应请求的个数。设置此值是1表示kafka broker在响应请求之前client不能再向同一个broker发送请求。注意:设置此参数是为了避免消息乱序
2是两个生产者,这时候消息如何确定消息的顺序呢。
两个生产者生产的消息无法保证顺序,因为它们本身就没有前后之分,它们是并发的关系。
leader=-1或者说没有leader的分区就是不可用分区
可以用过API的方式从Broker端获取,比如KafkaConsumer.partitionsFor方法
topic创建的时候指定了分区数
Zk集群没有一定要放在哪个城市。这个例子只是配合分区策略引出的,而且的确也有大厂这么使用。其实更好的做法还是多集群的方式。每个IDC有自己的Kafka集群,彼此同步。至于多topic的方式如果业务分割得清晰实际上是更好的解决方案:)
主要的机制是两阶段提交(2PC)。引入了事务协调器的组件帮助完成分布式事务
是因为broker端无法单独做出判断。另外写入之后无法直接丢弃,只能依靠其他字段实现跳过该消息
不支持
可以多个 topic
producer会向任意一个broker请求元数据,因为所有broker都缓存了相同的集群元数据信息
topic数量只要不是太多,通常没有什么影响。如果单台broker上分区数超过2k,那么可能要关注是否会出现性能问题了。
也不能说没有关系。客户端需要和topic下各个分区leader副本所在的broker进行连接的
集群元数据持久化在ZooKeeper中,同时也缓存在每台Broker的内存中,因此不需要请求ZooKeeper.
Clients端有个参数metadata.max.age.ms强制刷新元数据,默认的确是5分钟。新版本Clients不会与ZooKeeper交互,所以感觉和ZooKeeper没什么关系。。。
有可能也会连接这些Broker的。Clients获取到集群元数据后知道了集群所有Broker的连接信息。下次再次获取元数据时,它会选择一个负载最少的Broker进行连接。如果发现没有连接也会创建Socket,但其实它并不需要向这个Broker发送任何消息。
如果使用assign,则表明该consumer是独立consumer(standalone consumer),它不属于任何消费者组。独立consumer可以订阅任何分区,彼此之间也没有关系,即两个独立consumer可以订阅并消费相同的分区
不会。每个订阅者分配一部分分区消费
没有什么规定要求什么场景下需要订阅多个主题。事实上,对于默认的分区策略,一个组订阅多个主题的做法会导致分配的极不均匀,但我们依然还是能够找出一些场景,使得这么做是有意义的。比如消费者组订阅多组传感器的数据,我们不确定未来新增传感器的主题名到底是什么,但可以约定所有传感器的主题名以sensor开头,那么此时让group订阅以sensor开头的所有主题就能动态地检测后续新增的主题。这个场景是不是有意义些?
如果你的client端机器非常强劲,只启动一个consumer实例单线程消费未免有些浪费,你可以以启动多个线程的方式来充分利用资源。
可以删除。使用kafka-consumer-groups命令
目前不会 ???
可能出现gc导致rebalance的
社区希望对所有的东西都能有掌控度,而不是依赖其他第三方组件
Consumer group是第一个消费者订阅的时候创建的
这个消费者设置了相同的groupID,那么不论是否订阅该topic,都会属于这个消费者组。
社区2.3引入了static consumer,这样consumer程序正常的停机重启不会rebalance,可以试试.
不会的
不会重置,如果这个分区由组内其他consumer分配了,也是接着之前的进度继续消费。
可以
默认560个分区,3个副本。可以设置也可以自行创建
有,KafkaConsumer有offsetsForTimes方法
reassign操作很容易出错,不只是对__consumer_offsets。我个人的建议哈:
1. 业务低峰时段做;
2. 不要topic级别整体迁移,最好按照分区级别来做。比如一次迁移几个分区这样
topic过多其实是指分区数过多。会有两个可能的问题:1. controller无法管理这么多分区;2. 分区数过多导致broker物理随机IO增加,减少吞吐量。
第一个问题社区算是修复了吧,目前单controller能够支持20w的分区数,况且社区也在考虑做多controller方案;
第二个问题目前没有太多直接的修复举措,只能说具体问题具体分析吧
每个client都有自己的member id和client id用于区分彼此
如果是多个分区,即使是但consumer线程,也没法保证全局的顺序性。这是无法规避的
手动调用commitSync或commitAsync方法
Kafka自己管理的,其实和普通主题原理是类似的
位移主题也是主题,也要遵循Kafka底层的日志设计思路,即append-only log
每个Kafka集群都只有一个位移主题.
首先找到对应的Coordinator,Coordinator保存了这些数据,然后consumer向Coordinator发送请求去请求这些数据
不是。位移提交这件事从设计到实现与ZooKeeper完全没有关联了。
取最大的
0.10.1之前是在调用poll方法时发送的,0.10.1之后consumer使用单独的心跳线程来发送
别增加。目前源代码中内部topic的分区被hard code成50了,如果后面修改会造成各种问题。已经有对应的bug来解决此事了,但代码还没有merge
是的
针对整个group的。如果消费者组订阅信息发生变化也是会发生rebalance的。
0.9的确没有这个参数。你依然只能设置session.timeout.ms来规避
消息如果在max.poll.interval.ms时间内处理不完就会触发rebalance。社区提供该参数的目的就是为了把这个含义从session.timeout.ms中剥离,因此这是个与rebalance很有关系的参数
一旦Coordinator将consumer踢出组,该consumer实例会禁掉心跳并等待前端主线程重新加入组
65.brokder挂了,不会导致订阅主题的分区数发生变化吗,然后重平衡?
broker挂了,分区数不会变啊
会的。max.poll.interval.ms是rebalance的超时时间。broker端Coordinator挂掉不会引发rebalance
嗯,是的
consumer重启了,rebalance就开始了
不能保证~
会的。组成员发生了变更
消费完消息后需要再次调用poll方法才行。
试想如果heartbeat.interval.ms > session.timeout.ms,那么当下次发送心跳时,会话已经过期了,心跳也就没有意义了
如果是之前的版本,设置该参数长一点是有意义的。有了max.poll.interval.ms之后,session.timeout.ms就唯一被用于检测failed consumer了。所以还是尽早发现为好吧
每个consumer可能设置不同的session.timeout.ms
因为有新的分区需要被分配
很多流处理框架的Kafka connector都没有使用consumer group,而是直接使用standalone consumer,因为group机制不好把控
standalone consumer没有rebalance,也没有group提供的负载均衡,你需要自己实现。其他方面(比如位移提交)和group没有太大的不同
group.id是必须要设置的,否则会抛InvalidGroupIdException异常
不包括,因为你请求元数据的broker可能不是Coordinator,没有Coordinator的信息
是的。每个group都有一个与之对应的coordinator
lead越小意味着consumer消费的消息越来越接近被删除的边缘,显然是不好的
可能出现丢失数据了。lag<0一定要重点关注
82. 要梳理目前线上的 哪些生产者往哪些主题发消息以及哪些消费者消费某些主题。希望能快速获取并梳理出来 .
目前无法获取到集群中生产者的数量信息,因为broker端并没有这方面的记录。消费者的话可以使用kafka-consumer-groups命令来间接获取
你连接的是Broker的JMX端口吧,你需要连接consumer的JMX端口
消息里面有创建的时间戳,可以用程序自行计算
都可以
取决于auto.offset.reset的值
earliest : 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费
latest [默认] : 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据
none : topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出NoOffsetForPartitionException异常
不会引发lag,因为用的是AdminClient
不会引入rebalance,因为没有subscribe;
可以,因为AdminClient的listConsumerGroupOffsets访问所有分区
也不是绝对的相反关系,只是说明大概率情况下如果lag增加了,那么说明consumer消费速度慢了,自然已消费的位移就比较靠近起始位移了
你可以手动写代码实现。用AdminClient的各个API组合实现
其他主要参数:
replica.fetch.max.bytes=10020000
message.max.bytes=10000000
auto.leader.rebalance.enable=false
unclean.leader.election.enable=false
request.required.acks=-1
default.replication.factor=3
message.send.max.retries=5
auto.create.topics.enable=false
可能是因为你的__consumer_offsets主题的副本因子是1,导致位移提交无法写入了,严格来说这也算是一个小bug。不过你可以先确认下,比如这样:
bin/kafka-topics.sh --describe --bootstrap-server localhost:9092 --topic __consumer_offsets
要是2.0之前的版本,使用--zookeeper zk:port替换--bootstrap-server
嗯,就一直少一个副本了
试了以下几种方法都没有自动加入进来:
1、等了3天后还是没有加入到ISR;
2、然后重启kafka集群;
3、用kafka-reassign-partitions.sh命令重新分配分区;
针对此情况,请问一下有什么办法让它自动加入进来? 或者手工处理加入进来也可以。
有什么命令可以查看follower落后多少吗?
试试到ZooKeeper中手动删除/controller节点。这通常都是因为Controller与ZooKeeper状态不同步导致的。
试试这个命令吧: rmr /controller
确保在业务低峰时刻执行这个命令
Producer端认为消息已经成功提交的条件是:ISR中所有副本都已经保存了该消息,但producer并没有指定ISR中需要几个副本。这就是min.insync.replicas参数的作用。
正常情况下,如果5个副本都在ISR中,那么它们必须都同步才行,但如果4个副本不在ISR中了,不满足min.insync.replicas了,此时broker会抛出异常给producer,告诉producer这条消息无法正确保存.
只能把r2启动起来了,而且有可能出现数据丢失。因为Kafka承诺不丢消息也是有条件的
也不算丢数据,默认配置下如果ISR为空了,这个分区就不可用了,producer也无法向这个分区发送任何消息了。对于这种情况,Kafka不认为是丢数据
不会阻塞,你可以认为是不断轮询状态
不停地fetch,然后处理,之后再fetch。具体间隔没法配置
ISR中的follower副本非常有可能与leader不一致的。如果leader挂了,其他follower又都没有保存该消息,那么该消息是可能丢失的。如果你要避免这种情况,设置producer端的acks=all吧
follower被踢出ISR不代表它有问题了,至少不表示它挂了,可能只是阶段性的落后leader。当追上后还是可以将其重新加入到ISR中的
acks=all保证ISR中的所有副本都要同步
目前一旦出现partitioning,Kafka无法正常工作
默认情况下是CP,即先保证一致性。不过还是那句话,CAP理论研究学习可以,用于指导分布式系统实践非常不合适。
CAP理论:一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。
目前不会
可以的
一个分区有3个副本,一个 leader,2个follower。
producer向leader写了10条消息,follower1从leader处拷贝了5条消息,follower2从leader处拷贝了3条消息,
那么leader副本的LEO就是10,HW=3;follower1副本的LEO是5。
是有这种可能,如果你在意这种情况producer端设置acks=all就可以避免了
增加副本数
不会
不工作了
会的
113. 如果仅仅以 replica.lag.time.max.ms 决定 follower 是否应该加入 ISR 集合,是否存在这样一种情况,一个 follower 离线了一段时间之后重新上线,然后开始与 leader 同步,此时同步时间间隔在 replica.lag.time.max.ms 内,该 follower 成功加入到 ISR 集合,但是因为长时间失效,导致该 follower 的 LEO 值小于 leader 的 HW,如果此时 leader 宕机,并正好选择该 follower 作为新的 leader,这样是不是就丢消息了?
不会。ISR比较的是follower和leader的LEO,不是和leader的HW比较。
不能。acks的设置与否与ISR中有几个副本没有关系
使用kafka-reassign-partitions脚本可以,具体用法看一下--reassignment-json-file参数
不会丢失。还是那句话:Kafka只对已提交消息做持久化保证。如果你设置了最高等级的持久化需求(比如acks=all),那么follower副本没有同步完成前这条消息就不算已提交,也就不算丢失了。
未完成,待整理.............
原文引用:
Kafka核心技术与实战 - 胡夕