1. kafka的几个角色和概念
- 生产者和消费者
- 消费者组:一些消费者的组合,共同消费一个或几个topic。主要是对某个topic共同消费,提高消费效率,一般一个消费者组里的消费者都有一样的逻辑,一个消费者对应一个partition。
- broker:一个独立的kafka服务实例,多个broker组成一个集群。
- topic:生产者发送到特定的topic、消费者订阅特定的topic。
- partition:1个topic有多个partition,一个partition相当于一个队列,同一个topic上的partition可以分布在不同的broker上。生产者发送的消息其实是发给某个topic的某个partition上的,消费者订阅的消息其实是某个topic的某个partition的消息。多分区可以提高消费的并发能力,同一个topic分布到多个broker上,不同的消费者链接该topic的不同partition。
- 副本:副本是partition的副本,分为两个角色:
- leader:生产者和消费者都是直接跟partition的leader交互的
- follower:只是作为leader的数据备份,当leader挂了后,partition的follower会重新选举leader
用菜鸟驿站来类比kafka。
- broker和kafka集群:一个菜鸟驿站类比一个broker,假设有a、b、c 3个菜鸟驿站,就组成了一个有3个broker的kafka集群。
- 生产者和消费者:生产者是寄快递的人,消费者是收快递的居民。一个快递就是一个消息。一个居民就是一个消费者。
- 消费者组(consumer group):有2群住在附近的居民,一群只取衣物,另一群只取生鲜。这2群居民就是2个消费者组,他们分别消费同一个topic的消息,每个消息只会被其中一个居民取走,不会重复。
- topic和broker:每个驿站有室内和室外两个区域,室内都存放衣物,室外都存放生鲜食品。相当于这个集群有两个topic:“衣物topic”和“生鲜食品topic”,它们都横跨了3个broker。
- partition:驿站的室内室外2个区域都有不少货架,每个货架类比一个topic里的一个partition。
- 副本(leader和follower):每一个货架(partition)本来都有3层,但都分别被拆开成了3个1层的架子,分别摆在3个驿站上,来着同一个货架的3个架子中,有一个会被镀金,是leader架子,另外两个就是普通铁架子,是follower架子,当一个物品要放到菜鸟驿站的时候,只能放到这个镀金的架子上,它对应的两个铁架子上会神奇地自动复制各产生1个物品。取物品也只能从镀金架子上取。假设a驿站关门了,a驿站上的镀金架子就获取不到了,其他两个驿站对应的铁架子会有一个被选出来镀上金。
2. Kafka的高吞吐是如何实现的
- 顺序读写磁盘:消息顺序写入磁盘,避免随机读写磁盘的开销。
- 零拷贝技术:磁盘读写用mmap;发送到网络用sendfile。
- 批量处理:生产者和消费者可以将多个消息打包成一个批次进行发送和处理,减少网络开销。
3. 如何优化Kafka的性能
- 合理设置分区数量:根据数据量和吞吐量需求,避免分区过多或过少。
- 调整生产者和消费者的参数:如批次大小、拉取频率、异步发送等参数,以提高性能。
- 优化硬件资源:如增加内存、使用高速磁盘等。
4. kafka如何保证消息消费的顺序性
kafka保证在单个partition内消息是严格有序的。发送消息的时候指定partition,同一个事情的消息发到同一个partition里。
例如,在一个订单处理系统中,对于同一个订单的操作日志可以发送到同一个分区,这样在消费时就能按照操作的发生顺序来处理订单状态的变化。
5. kafka如合保证消息不丢失
5.1. 生产者发送失败重试
生产者发送消息是异步的,send()后,可用get()获取发送结果。可设置生产者发送失败后的重试次数。
5.2. 消费者手动确认消费结果
生产者投递信息到partition里是追加的,会有一个offset的偏移量,如果是自动确认,消费者拿走这个消息后,该offset的消息就被消费了,如果消费者刚拿走还没来得及处理就挂了,这条消息就丢失了。所以解决方法是等消费者消费完成,再告诉partition该offset消费了。
但这样可能导致重复消费(如何解决见下文),比如消费者消费完了还没来得及告诉partition,消费者就挂了,他再启动起来,还是可以获取到该消息。
5.3. 死信队列
消费失败也会重试,不会无限重试,重试次数到了会跳过当前消息,继续执行后面的消息,不会卡住。这种没有正确被消费的消息会放到死信队列(Dead Letter Queue,简称 DLQ) 里,可以被进一步分析和处理。
5.4. 多个partition副本确认
kafka会把消息写到硬盘上(顺序写、零拷贝,所以比较快)。
kafka可以配置ack=all,这样partition对应的所有follower都同步了数据后,leader才确认消息被收到,但这样延时会比较高,一般设置副本数要大于1,这样即安全,性能也还行。
6.如何保证kafka消息不重复
消费方做幂等。