kafka知识点

292 阅读11分钟

kafka知识体系 (1).png

一、介绍下kafka

kafka简介: kafka是一个分布式的流式处理平台,具有高吞吐、可持久化、可水平扩展、支持流数据处理等特性。

kafka功能:

  1. 消息系统:具备系统解耦、异步等功能的消息队列
  2. 存储系统:kafka可以把数据持久化到磁盘。得益于持久化和多副本机制。设置永久或者启动日志压缩
  3. 流处理平台:建立实时的数据通道来处理数据。

kafka架构:

kafka架构.png

producer
consumer
broker
topic
partition
leader副本
follower副本

二、kafka多副本是怎么管理的

kafka多副本管理.png

AR: 分区中的所有副本,assigned-sync-replication

ISR: 所有与leader副本保持一致的副本(包括leader副本),in-sync-replication

OSR: 与leader副本同步相差较多的副本, out-sync-replication

leader负责维护和跟踪AR集合里所有follower副本的滞后状态,滞后过多放到OSR集合,进度赶上来放到ISR集合。

理论上来讲,只有ISR里的follower副本才有资格选举leader副本

副本leader选举:

谁来实施:controller负责具体实施

选举时间:leader副本所在broker挂掉后

谁来选举:ISR集合里的follower副本 优先副本就是说在AR集合中的第一个副本。理想情况下优先副本就是 leader 副本。优先副本选举就是促使优先副本成为leader副本,从而维护集群的负载均衡

三、生产者发送消息的模式

1. 发后即忘: 只管发送,不管发送是否成功。效率高,但是可靠性差。

2. 同步(sync): producer.send()返回一个Future对象,发送一个消息之前确认上一条消息成功

3. 异步(async): producer.send()传入一个回调函数,消息不管成功失败都调用这个函数,这样就算异步发送。这种情况对于消息失败是重试或者记录日志都取决于调用方

四、生产者发送消息的分区策略

发送消息的分区策略.png

1. 指定分区: 指定分区发送

2. 轮询: key为空,随机到某个分区

3. 通过key指定: key不为空,通过hash值映射到指定分区

4. 自定义策略: 实现org.apache.kafka.clients.producer.Partitioner

五、kafka支持读写分离么

不支持读写分离

kafka即使不支持读写分离也能在一定程度上实现负载均衡。 对于kafka架构来讲,实现读写分离有几个问题

  1. 节点之间数据不一致的问题
  2. 延时问题

六、kafka如何实现负载均衡

kafka如何实现负载均衡: 根据kafka主写主读的架构设计,是通过分区来实现一定程度的负载均衡,每个broker都有消费者拉取消息,每个broker都有生产者生产消息。

kafka负载均衡的问题: 会有一些情况导致不是那么均衡

  1. broker端分配不均:
  2. 生产者发送消息不均:
  3. 消费者拉消息不均
  4. leader副本切换不均:当主副本进行了切换或者分区副本进行了重分配,可能导致各个broker的leader副本分配不均。

七、怎么保证消息不丢失

可以拆成两个问题,1是什么情况下会丢消息,2然后根据这些情况尽可能保证不丢

producer角度:

1>. acks: 分区中多少副本收到消息才算成功,acks=-1或者acks=all,需要等待ISR中的所有副本都成功写入消息后才能收到服务端的响应,可靠性高。但是如果ISR中只有leader副本也可能有问题

2>. send重试 通过同步或者异步的方式发送,获取返回结果,进行失败重试

consumer角度:

手动提交位移: 当消费者消费到消息后,就会自动提交位移,但是如果消费出错就会丢失。可以先处理逻辑再手动提交位移,这样能避免丢失,也可能重复。

broker角度

leader副本所在的broker挂掉,follower副本需要重选举,但是没来得及同步,也会导致丢失 unclean.leader.election.enable = false,进度不达标不参与选举

kafka的消息传输一致性最多一次、最少一次、精准一次

1. 精准一次

定义:即使生产者重试发送消息,也只会让消息被发送给消费者一次

方案:手动提交位移,结合唯一id保证消息的原子性

2. 至少一次

定义:重试,消息可能被重复消费

出现:如果生产者接收ack超时或者收到了错误,就会重试。 如果broker恰好在消息已经成功写入后,在发送ack前出现故障,就会有两条一样的消息,消费者也会出现重复消费

3. 最多一次

定义:不重试,消息可能会没有被消费

怎么出现的:生产者接收ack超时或者收到了错误,不充实

kafka丢数据、重复消费、顺序消费问题

丢数据: 分为producer/consumer/broker三种

手动提交位移如何实现:

image.png

重复消费:

幂等性保障:

  1. 找出业务主键ID标记。比如订单号+订单状态。
  2. 【redis前置处理】在处理之前先去redis查一下是否存在该key,如果存在说明处理过了,直接丢掉。没处理过继续处理。
  3. 【mysql最终保障】依赖数据库的唯一索引做最终保证来实现幂等性

顺序消费

  1. 大宽表:多个字段多个状态,每一个状态单独分出一个独立字段,消息来时,只更新对应字段,消息只会存在短暂的消息不一致问题,状态最终还是一直的。
  2. 消息补偿机制:另一个进行消费相同topic的数据,消息落盘,延迟处理。将消息与DB进行对比,发现不一致,再重新发送消息至主进程。
  3. 发到相同的parition,因为一个partition是有一个consumer消费,能解决顺序问题。但是单线程容易堵塞。

image.png

八、如何增加消费端的消费能力

  1. 可以考虑增加topic的分区数,同时增加消费数量,消费者数=分区数
  2. 如果消费不及时,采用多线程消费,同时优化业务逻辑(同样的分区数,人家可以你为啥不可以)

九、消费者的分区分配策略

1. RangeAssignor分配策略(默认)

基于topic进行分配

2. RoundRobinAssignor分配策略

轮询是把partition作为最小单元

**3. StickyAssignor分配策略 **

分区的分配尽可能均匀;分区的分配尽可能和上次一致

kafka重平衡问题

juejin.cn/post/701245…

image.png

十、controller是什么,有什么用

kafka集群有多个broker,其中有一个broker被选举为controlller,负责整个集群分区和副本的状态管理。

  • 当某个分区的leader副本发生故障时,controller负责新的leader副本选举
  • 当检测到某个分区的ISR集合发生变化时,controller告诉其他broker更新元信息
  • 为某个topic增加分区数量时,controller负责分区的重新分配

十一、controller选举

kafka控制器信息存储在zookeeper的/controller节点,有三种情景会触发选举

  • 集群从零启动
  • /controller节点消失
  • /controller节点数据发生变化

每个broker启动时,尝试读取/controller节点的brokerid的值,如果值不是-1,则表示已经有conteoller,放弃。

如果Zookeeper中不存在/controller 节点,或者这个节点的数据异常,那么就会尝试去创建/controller 节点,创建成功的那个 broker 就会成为控制器

十二、kafka为什么这么快

1. 顺序读写

磁盘分为顺序读写和随机读写,基于磁盘的随机读写比较慢,但是顺序读写很快,kafka就是基于顺序读写

2. page cache

利用操作系统本身的内存而不是jvm的内存

3. 零拷贝(可以深入了解)

直接将数据从内核空间的读写缓冲区拷贝到内核空间的socket缓冲区,然后再写到NIC缓冲区,避免了用户空间和内核空间的转换。

4. 分区分段

Kafka的message是按topic分类存储的,topic中的数据又是按照分区存储到不同broker节点。每个partition对应了操作系统上的一个文件夹,partition实际上又是按照segment分段存储的。

5. 批量读写

kafka读写消息是批量的而不是单条的,可以节约带宽

6. 批量压缩

所有的消息都会进行合理的压缩,减少IO损耗,提高IO速度。

十三、Kafka、RabbitMQ、RocketMQ的对比

性能: 消息中间件的性能主要体现在吞吐量。kafka吞吐量比Rabbit高出一两个数量级。kafka是单机QPS达到百万级,Rabbit万级别,Rocket单机写入TPS是7万/s

数据可靠性: kafka具有多副本机制,数据可靠性较高。rocketmq支持异步实时刷盘

服务可用性: kafka集群部署,结合分区和多副本设计,单节点宕机无影响。rabbitmq支持集群。rocketmq是分布式架构,可用性高

功能上: kafka和rabbitmq是比较主流的消息中间件,基本功能差不多,有一些特殊功能存在差异。 rocketmq在阿里内部使用比较多。

十四、实际中遇到的问题与解决

1. 消费积压问题

问题:消息中间件异常导致消息消费失败,大量kafka消费失败报警,经相关负责人了解到是kafka集群某节点内存故障导。业务侧观测到获取取元数据超时,消费失败,从而产生积压。

解决:

1> 如果集群异常或者未完全恢复,不要上线操作

2> kafka组件搞个开关,不要影响其他正常的业务

3> 上线服务可以将故障kafka节点从配置中删除,再进行上线重启

问题: 业务增长,生产者消息量超出消费者的消费能力

解决:

1> 提升单条消息的处理速度(优化逻辑/慢查询/日志不合理)

2> 对partition扩容增加partition数量

3> 消费端改为多线程并发消费

问题: 收到延迟报警,从kafka manager看,该topic有3个分区,两台机器来回变换的消费2号分区,消费进度没有任何变化;从 broker 端日志看,该消费组在频繁的进行rebalance

查看上下记录看懂设置了max.poll.records=20, max.poll.interval.ms=1000,也就是consumer一次最多拉20条消息,最长时间间隔1秒,必须处理完。否则,broker会认为消费者处理太慢而被踢出消费组,从而导致消费组rebalance.根据kafka机制,rebalance过程是不会消费消息的。所以两台机器轮流拉取消息,循环进行rebalance,消息就积压了。

解决: 消费者客户端减小 max.poll.records或者增大max.poll.interval.ms 默认5分钟500

十五、 RocketMQ的特点

juejin.cn/post/706606…

image.png

  1. 亿级别消息的堆积能力,单个队列的百万级消息的累积容量
  2. 高可用性: Broker支持多master多slave的同步双写以及master多slave的异步复制模式,其中同步双写可保证消息不丢失
  3. 高可靠性: 生产者发送消息三种方式,同步、异步和单向,其中同步和异步都可以保证消息成功发送。 Broker刷盘策略:同步刷盘和异步刷盘,其中同步刷盘可以保证消息成功存储到磁盘。消费者的消费模式也有集群和广播消息两种,默认集群消费,如果集群模式消费着挂了,一个组中的其他消费着会接替其消费
  4. 支持分布式事务消息: 采用半消息确认和消息回查机制来保证分布式事务消息的。
  5. 支持消息过滤: 采用消费业务端的tag过滤
  6. 支持顺序消费: 消息在Broker中采用队列的FIFO模式存储,发送是有序的,保证消费有序即可。
  7. 支持定时消息和延迟消息: Broker中有定时消息的机制,消息发送到Broker,不会立即被Consumer消息,会等到一定时间才被消费,延迟消息同。