Kafka基本概念:
1、Producer:消息和数据的生产者。向Kafka的一个Topic发布消息的进程/代码/服务
2、Consumer:消息和数据的消费者。订阅数据(Topic)并且处理其发布的消息的进程/代码/服务
3、Consumer Group:对于一个Topic,会广播给不同的group,但一个group中只有一个Consumer可以消费该消息。
4、Broker:Kafka集群中的每个Kafka节点。
5、Topic:Kafka消息的类别,对数据进行区分、隔离。
6、Partition:Kafka下消息数据存储的基本单元、一个Topic数据会被分散存储到多个Partition,每个Partition是有序的。
注意:6.1、每个Topic下多个消息,有多个Partition。
消费者的数目小于或等于Partition数目 理解:每个消费者消费一个Partition,如果消费者的数目大于Partition数目,会出现多个消费者重复消费多个Partition。
7、Replication:同一个Partition可能有多个Replication(数据副本),多个Replication之间的数据都是一样的,增加容错性和可扩展性。
注意:7.1、当集群中有Broker挂掉的情况,系统可以主动使用Replicas提供服务。
7.2、系统默认设置的每个Topic的Replication系数为1(没有副本:节省资源)。在创建Topic时设置。
7.3、所有的读写操作又Leader负责。Followers只是做数据备份。
7.4、Follower必须及时复制Leader的数据。
8、Replication Leader:一个Partition上有多个Replication。Replication Leader决策使用那个Replication来与Producer和Consumer交互(负责所有的读写操作)。
注意:8.1、无论一个Partition有多少个Replication,都只会有一个Replication Leader。并且只有Replication Leader可以与Producer和Consumer交互,其他Replication只是备份数据。
9、Replication Manager:
负责管理当前Broker所有分区和副本的信息,处理KafkaController发起的一些请求。副本状态的切换,添加/读取消息等。
当Replication Leader挂掉了,Replication Manager会重新从其他Replication中选举出Replication Leader。
Kafka基本结构:
Kafka是强依赖于Zookeeper。Kafka每个Broker信息在ZooKeeper上。所有的Topic以及Patition分布也在Zookeeper上。Producer生产的消息会保存在Kafka集群中的Broker的磁盘空间上。Consumer通过订阅Kafka Topic消费时,会从Zookeeper上获取对应的Broker信息。然后主动去对应的Kafka Broker pull对应的消息。
面试常见问题:
1、如何保证消息不被重复消费?
可以换个思路,在消费端保证消费程序的幂等性,无论消费如何重复,程序最终运行的结果都是一致的,比如消费写库:增加乐观锁或者使用ON DUPLICATE KEY UPDATE,如果存在则修改
2、如何处理消息丢失的问题(可靠性)
消费端:由自动提交OFFSET,改为手动提交OFFSET,保证消息成功消费后再提交OFFSET
生产端:kafka 服务端设置min.insync.replicas参数:这个值必须大于 1,这个是要求一个 leader 至少感知到有至少一个 follower 还跟自己保持联系,没掉队,确保 leader 挂了还有一个 follower。
producer 端设置acks=all:这个是要求每条数据,必须是写入所有 replica 之后,才能认为是写成功了。
producer 端设置重试参数retries=MAX,一旦写入失败,就会重试。
3、消息堆积的问题
Kafka会监控消息的状态,如果出现堆积会发生报警
如何处理:
动态的增加多个partition
新加一个新的TOPIC,然后增加老TOPIC,10倍的partition,写一个分发程序将积压的消息均匀的轮询写入这些队列,然后部署10 倍的机器部署 consumer,每一批 consumer 消费 1 个临时的队列,消费完后恢复原架构。
4、顺序消费问题:
全局顺序性、分区顺序性。在生产消息时,一个 topic,一个 partition,一个 consumer,内部单线程消费,单线程吞吐量太低,一般不会用这个。写 N 个内存 queue,具有相同 key 的数据都到同一个内存 queue;然后对于 N 个线程,每个线程分别消费一个内存 queue 即可,这样就能保证顺序性。