KAFKA 当前版本 2.2.1 项目使用 2.X
问题 | 答案 |
---|---|
kafka acks参数对消息持久化的影响 | acks参数,是在KafkaProducer,也就是生产者客户端里设置 acks=0 只要把消息发送出去,不管那条数据有没有在Partition Leader上落到磁盘,我就不管他了,直接就认为这个消息发送成功了。 影响:Partition Leader所在Broker就直接挂,会导致这条消息就丢失了 acks = 1 默认的设置 只要Partition Leader接收到消息而且写入本地磁盘了,就认为成功了,不管他其他的Follower有没有同步过去这条消息了。 影响:Partition Leader刚刚接收到消息,Follower还没来得及同步过去,结果Leader所在的broker宕机了,此时也会导致这条消息丢失 acks=all Partition Leader接收到消息之后,还必须要求ISR列表里跟Leader保持同步的那些Follower都要把消息同步过去,才能认为这条消息是写入成功了。 影响:如果你的Partition只有一个副本,也就是一个Leader,任何Follower都没有,也会导致数据丢失 |
kafka参数调优 参考: | Kafka生产端的示例代码 buffer.memory KafkaProducer本地的内存缓冲,默认值是32MB。内存缓冲里大量的消息会缓冲在里面,形成一个一个的Batch,每个Batch里包含多条消息。然后KafkaProducer有一个Sender线程会把多个Batch打包成一个Request发送到Kafka服务器上去。避免了一条消息一次网络请求。从而提升了吞吐量,即单位时间内发送的数据量。 设置太小:内存缓冲快速被写满,Sender线程来不及把Request发送到Kafka服务器,会阻塞用户线程 设置太大:浪费内存缓冲 方案:结合自己的实际情况来进行压测
batch.size 多大数据打包为一个Batch就可以发送出去 设置太大:数据老是缓冲在Batch里迟迟不发送出去,发送消息的延迟就会很高 设置太小:发送频率太高,降低整体吞吐量 linger.ms 消息一旦写入一个Batch,最多等待这么多时间,他一定会跟着Batch一起发送出去,要配合batch.size一起来设置 max.request.size 每次发送给Kafka服务器请求的最大大小,同时也会限制你一条消息的最大大小也不能超过这个参数设置的值 retries和retries.backoff.ms决定了重试机制,也就是如果一个请求失败了可以重试几次,每次重试的间隔是多少毫秒 acks 见上 |
Kafka如何通过精妙的架构设计优化JVM GC问题? | Batch里的数据都发送过去了,现在Batch里的数据应该怎么处理? Kafka客户端内部用了缓冲池的机制 缓冲池里会有很多的内存块,需要创建一个新的Batch,就从缓冲池里取一个内存块就可以了,如果Batch被发送到Kafka服务器了,此时Batch底层的内存块就直接还回缓冲池就可以了。
|
消费到的消息处理失败怎么办? | 死信队列的使用:处理失败的消息 消息处理失败了之后,MQ就会把这条消息转入提前设置好的一个死信队列中。 消费者恢复正常后,这个后台线程就从死信队列消费出 |
简述一下Kafka中的分区分配? | 生产者的分区分配 为每条消息指定其所要发往的分区
key不为null,那么默认的分区器会对key进行哈希,那么计算得到的分区号会是所有分区中的任意一个 key为null,那么消息将会以轮询的方式发往主题内的各个可用分区
消费者的分区分配 为消费者指定其可以消费消息的分区 消费者的分区分配而言,Kafka自身提供了三种策略,分别为RangeAssignor、RoundRobinAssignor以及StickyAssignor,可以通过实现ParitionAssignor接口来自定义分区分配策略。
broker端的分区分配 为集群制定创建主题时的分区副本分配方案,即在哪个broker中创建哪些分区的副本。 创建主题时,如果使用了replica-assignment参数,那么就按照指定的方案来进行分区副本的创建; 如果没有使用replica-assignment参数,那么就需要按照内部的逻辑来计算分配方案了。 |
Kafka中的选举时怎么回事?
| 控制器的选举 在Kafka集群中会有一个或多个broker,其中有一个broker会被选举为控制器(Kafka Controller),它负责管理整个集群中所有分区和副本的状态等工作。 Kafka Controller的选举是依赖Zookeeper来实现的,在Kafka集群中哪个broker能够成功创建/controller这个临时(EPHEMERAL)节点他就可以成为Kafka Controller。
分区leader的选举 分区leader副本的选举由Kafka Controller 负责具体实施。 当创建分区(创建主题或增加分区都有创建分区的动作)或分区上线(比如分区中原先的leader副本下线,此时分区需要选举一个新的leader上线来对外提供服务)的时候都需要执行leader的选举动作。 基本思路是按照AR集合中副本的顺序查找第一个存活的副本,并且这个副本在ISR集合中。
消费者相关的选举 组协调器GroupCoordinator需要为消费组内的消费者选举出一个消费组的leader,这个选举的算法也很简单,分两种情况分析。 如果消费组内还没有leader,那么第一个加入消费组的消费者即为消费组的leader。 如果某一时刻leader消费者由于某些原因退出了消费组,那么会重新选举一个新的leader,这个重新选举leader的过程又更“随意”了 |
Kafka如何实现高吞吐? 参考: |
|
Kafka partition还能细分吗? 参考: https://www.infoq.cn/article/depth-interpretation-of-kafka-data-reliability | 每个 partition(目录) 相当于一个巨型文件被平均分配到多个大小相等的 segment(段) 数据文件中(每个 segment 文件中消息数量不一定相等)这种特性也方便 old segment 的删除,即方便已被消费的消息的清理,提高磁盘的利用率。
segment 文件由两部分组成,分别为“.index”文件和“.log”文件,分别表示为 segment 索引文件和数据文件。 |
为什么Kafka不支持读写分离? Kafka 读、写都是走leader 主写主读 参考:
| 主写从读问题:数据一致性问题(一段时间内主、从数据不一致);延时问题(主从同步过磁盘延时高)
Kafka 只支持主写主读有几个优点: 简化代码的 实现逻辑,减少出错的可能 ; 没有延时的影响 ; 不会出现数据不一致情况 ; 将负载粒度细化均摊,与主写从读相比,不仅负载效能更好,而 且对用户可控; |
Kafka中的事务、幂等 参考: | kafka开启幂等性功能 : 生产者 设置参数 enable.idempotence true 如何实现幂等性: 引入 producer id(简称PID,新的生产者实例在初始化的时候都会被分配一个PID)和序列号(sequence number)。对于每个PID,消息发送到的每一个分区都有对应的序列号,这些序列号从0开始单调递增。生产者每发送一条消息就会将对应的序列号的值加1。 只能保证单分区的幂等
事务:生产者提供唯一 transactionalId,与PID一一对应,获取一个单调递增的producer epoch;具有相同transactionalId的新生产者实例被创建且工作的时候,旧的且拥有相同transactionalId的生产者实例将不再工作 事务相关方法:initTransactions() beginTransaction() sendOffsetsToTransaction() commitTransaction() abortTransaction() 消费端事务: isolation.level 设置事务隔离级别 消息类型:普通消息,控制消息(ControlBatch,记录是否是事务消息以及事务的状态) |
Kafka日志清理策略 参考: | Kafka中每一个分区partition都对应一个日志文件,日志文件又可以分为多个日志分段文件 两种日志清理策略: log.cleanup.policy delete删除 compact压缩
日志删除策略: 基于时间(默认7天过期):查找过期的日志分段文件 先查索引修改时间,再查文件修改时间;须要保证有一个活跃的日志分段activeSegment;日志分段文件添加上“.deleted”的后缀,最后由定时任务执行删除,默认1分钟执行一次 基于日志大小:当前日志的大小是否超过设定的阈值retentionSize 基于日志起始偏移量:小于logStartOffset可以删除 |
kafka 消息格式演变
| offset:用来标志它在partition中的偏移量 逻辑值 message size:表示消息的大小 V0版本消息最小14B Record : 消息实体信息
|
kafka中延时操作 生产者中没数据了消费者会一直拉吗? | Kafka延迟操作:读日志文件,如果没有足够的消息,会创建一个延时拉取操作,以等待拉取到足够数量的消息 延时操作:超时时间(超时时间内完成则正常返回) ,触发时机(超时触发或外部事件,外部事件可能是HW增长) |
Kafka的用途有哪些?使用场景如何? | 异步处理 、解耦、削峰、提速 消息,网站活动追踪,监测指标,日志聚合 |
Kafka中的ISR、AR又代表什么?ISR的伸缩又指什么? LEO , HW | ISR:In-Sync Replicas 副本同步队列 LEO,LogEndOffset 的缩写,表示每个 partition 的 log 最后一条 Message 的位置 HW 俗称高水位,HighWatermark 的缩写,取一个 partition 对应的 ISR 中最小的 LEO 作为 HW,consumer 最多只能消费到 HW 所在的位置。 LSO:Last Stable Offset 对未完成的事务而言,LSO 的值等于事务中第一条消息的位置(firstUnstableOffset),对已完成的事务而言,它的值同 HW 相同 LW:Low Watermark 低水位, 代表 AR 集合中最小的 logStartOffset 值 |
Kafka中是怎么体现消息顺序性的? | kafka每个partition中的消息在写入时都是有序的,消费时,每个partition只能被每一个group中的一个消费者消费,保证了消费时也是有序的。 |
kafka维护消费状态跟踪的方法 | Topic被分成了若干分区,每个分区在同一时间只被一个consumer消费。这意味着每个分区被消费的消息在日志中的位置仅仅是一个简单的整数:offset。这样就很容易标记每个分区消费状态就很容易了,仅仅需要一个整数而已。这样消费状态的跟踪就很简单了。 |
kafka 消息丢失和消息重复处理方式 | 消息丢失解决方案: 首先对kafka进行限速, 其次启用重试机制,重试间隔时间设置长一些,最后Kafka设置acks=all,即需要相应的所有处于ISR的分区都确认收到该消息后,才算发送成功
消息重复解决方案: 消息可以使用唯一id标识 生产者(ack=all 代表至少成功发送一次) 消费者 (offset手动提交,业务逻辑成功处理后,提交offset) 落表(主键或者唯一索引的方式,避免重复数据) 业务逻辑处理(选择唯一主键存储到Redis或者mongdb中,先查询是否存在,若存在则不处理;若不存在,先插入Redis或Mongdb,再进行业务逻辑处理) |
消息回溯 |
|
延时队列 | kafka 不支持延迟队列,不过可以基于时间轮实现,或者借助于redis实现等 |
kafka rabbitMq 参考: https://www.cnblogs.com/mengchunchen/p/9999774.html kafka VS RocketMQ http://jm.taobao.org/2016/03/24/rmq-vs-kafka/ | kafka : 性能好,吞吐量高,单机十万级别,高可用 缺点:消息重复消费 rabbitMq:RabbitMQ吞吐量稍微低些,实现的机制比较重;erlang开发,很难去看懂源码 RocketMQ(阿里):可靠性、性能都还不错,功能比较完善(阿里)
kafka VS RocketMQ 数据可靠性: kafka 只支持异步刷盘 RocketMQ支持同步刷盘和异步刷盘 (刷盘:内存写到磁盘) 性能对比: kafka 单机 TPS 百万级 RocketMQ 单机TPS 十万级 功能对比: 消费失败自动重试,事物消息,定时消息 kafka 不支持 RocketMQ支持 |