kafka知识整理
1、什么是kafka?
Kafka是最初由Linkedin公司开发,是一个分布式、支持分区的(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实时的处理大量数据以满足各种需求场景:比如基于hadoop的批处理系统、低延迟的实时系统、storm/Spark流式处理引擎,web/nginx日志、访问日志,消息服务等等,用scala语言编写.
从Kafka2.8版本开始,可以不用Apache Zookeeper来作为Kafka的依赖组件了,官网把这种称之为KRaft模式。Kafka使用Zookeeper来存储有关分区和Broker的元数据,并选择一个Broker作为Kafka的Controller。现在官网打算删除对Zookeeper的依赖,让Kafka能够以更具扩展性和更加强大的方式管理元数据,从而支持更多分区。(但还不太完善)。
2、kafka特性
高吞吐量、低延迟:kafka每秒可以处理几十万条消息,即使存储了许多TB的消息,它也能保持稳定的性能。
高性能:单节点支持上千个客户端,并保证零停机(集群中允许某个机器宕机)和零数据丢失。
持久化数据存储:将消息持久化到磁盘。通过将数据持久化到硬盘以及replication防止数据丢失。
如何保证速度:
1、零拷贝
2、顺序读,顺序写
3、利用Linux的页缓存
分布式系统,易于向外热扩展:所有的Producer、Broker和Consumer都会有多个,均为分布式的。无需停机即可扩展机器。多个Producer、Consumer可能是不同的应用。
可靠性 :Kafka是分布式,分区,复制和容错的。
客户端状态维护:消息被处理的状态是在Consumer端维护,而不是由server端维护。当失败时能自动平衡。
3、kafka使用场景
日志收集:一个公司可以用Kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、Hbase、Solr等。
消息系统:解耦和生产者和消费者、缓存消息等。
用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。
运营指标:Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
流式处理:比如spark streaming和storm
4、kafka基本概念
Broker:消息中间件处理节点。对于Kafka而言,Broker可以简单地看作一个独立的Kafka服务节点或Kafka服务实例。一个kafka集群由多个 broker 组成。一个 broker可以容纳多个 topic。
Topic:kafka根据topic对消息进行归类,发布到kafka集群的每个消息都需要指定一个topic。
Producer(生产者):消息生产者,向Broker发送消息的客户端。
Consumer(消费者):消息消费者,向Broker读取消息的客户端。
Consumer Group(消费者组):每个consumer都属于一个特定的group组,一个group组可以包含多个consumer,但一个组中只会有一个consumer消费数据。
offset(偏移量):在 Kafka 中,每个 主题分区下的每条消息都被赋予了一个唯一的 ID 数值,用于标识它在分区中的位置。这个 ID 数值,就被称为位移,或者叫偏移量。一旦消息被写入到分区日志,它的位移值将不能 被修改。
5、kafka的简单消费原理
1、生产者将消息发送给broker,broker会将消息保存在本地的日志文件中。例如/usr/local/kafka/主题-分区/00000000.log
2、消息的保存是有序的,通过偏移量来描述消息的有序性
3、消费者消费时也是通过偏移量来描述当前要消费的那条消息的位置

消费策略:
ealiest:当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费。
latest:当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据。
6、什么是单播和多播?
单播消息:同一个消费组中只能有一个消费者收到一个topic中的消息。
多播消息:一条消息能够被多个消费组中的一个消费者消费的模式称为多播。
7、主题和分区
主题是一个逻辑上的概念,它还可以细分为多个分区,一个分区只属于单个主题,很多时候也会把分区称为主题分区(Topic-Partition)。同一主题下的不同分区包含的消息是不同的,分区在存储层面可以看作一个可追加的日志(Log)文件,消息在被追加到分区日志文件的时候都会分配一个特定的偏移量(offset)
8、副本的概念
kafka为分区引入了多副本(Replica)机制,通过增加副本数量可以提升容灾能力。同一分区的不同副本中保存的是相同消息(在同一时刻,副本之前并非完全一样),副本之间是“一主多从”的关系,其中leader副本负责处理读写请求,follower副本只负责与leader副本的消息同步。副本处于不同的broker中,当leader副本出现故障时,从follower副本中重新选举新的leader副本对外提供服务。Kafka通过多副本机制实现了故障的自动转移,当Kafka集群中某个broker失效时扔然能够保证服务可用。
如下图,Kfaka集群中有4个broker,某个主题中有3个分区,且副本因子(即副本个数)也为3,如此每个分区便有1个leader副本和2个follower副本。生产者和消费者只与leader副本进行交互,而follower副本只负责消息的同步,很多时候follower副本中的消息相对leader副本而言会有一定的滞后。

broker,主题,分区,副本概念总结:
集群中有多个broker,创建主题时可以指明主题有多个分区(把消息拆分到多个分区中存储),可以为分区创建多个副本,不同的副本存放在不同的broker中。
副本和leader之间的区别:
Kafka 副本当前分为领导者副本和追随者副本。只有 Leader 副本才能 对外提供读写服务,响应 Clients 端的请求。Follower 副本只是采用拉(PULL)的方 式,被动地同步 Leader 副本中的数据,并且在 Leader 副本所在的 Broker 宕机后,随时 准备应聘 Leader 副本。
9、kafka集群消费

- kafka每个partition中的消息在写入时都是有序的,一个partition只能被一个消费组里的某一个消费者消费,从而保证消费顺序(但会牺牲性能)。但是多个partition的多个消费者消费的总的顺序是得不到保证的。
- partition的数量决定了消费者的数量,建议同一消费组消费者数量不超过partition的数量,否则多的消费者消费不到消息。
- 如果消费者挂了,会触发rebalance机制,会让其他消费者来消费该分区。
10、什么是ISR、AR?
ISR:In-Sync Replicas 副本同步队列。
AR:Assigned Replicas 所有副本。
ISR是由leader维护,follower从leader同步数据有一些延迟(包括延迟时间replica.lag.time.max.ms和延迟条数replica.lag.max.messages两个维度, 当前最新的版本0.10.x中只支持replica.lag.time.max.ms这个维度),任意一个超过阈值都会把follower剔除出ISR, 存入OSR(Outof-Sync Replicas)列表,新加入的follower也会先存放在OSR中。AR=ISR+OSR。
11、ack 为 0, 1, -1 的时候代表啥, 设置 -1 的时候,什么情况下,leader 会认为一条消息 commit了
1、1(默认) 数据发送到Kafka后,经过leader成功接收消息的的确认,就算是发送成功了。在这种情况下,如果leader宕机了,则会丢失数据。
2、0 生产者将数据发送出去就不管了,不去等待任何返回。这种情况下数据传输效率最高,但是数据可靠性确是最低的。
3、-1 producer需要等待ISR中的所有follower都确认接收到数据后才算一次发送完成,可靠性最高。当ISR中所有Replica都向Leader发送ACK时,leader才commit,这时候producer才能认为一个请求中的消息都commit了。
12、kafka中的controller
每个启动时向zk创建一个序号临时节点,获得需要最小的broker作为集群中的controller。负责的事情:
- 当集群中有一个副本的leader挂掉,需要在集群中选举一个新的leader,选举的规则从isr集合中最左边获得。
- 当集群中有broker新增或减少,controller会同步信息给其他broker。
- 当集群中有分区新增或减少,controller会同步信息给其他broker。
13、rebalance机制
Rebalance 本质上是一种协议,规定了一个 Consumer Group 下的所有 consumer 如何达成一致,来分配订阅 Topic 的每个分区。
前提:消费组中的消费组没有指明分区来消费。触发的条件:当消费者和分区关系发生变化。
消费策略:
- range策略:按照分区序号排序,假设
n=分区数/消费者数量=3,m=分区数%消费者数量 = 1,那么前m个消费者每个分配n+1个分区,后面的(消费者数量-m)个消费者每个分配n个分区。比如分区0-3给一个consumer,分区4-6给一个consumer,分区7-9给一个consumer(即较靠前消费到n+1个分区,之后的消费到n个分区)。 - round-robin轮询策略:轮询分配,比如分区0、3、6、9给一个consumer,分区1、4、7给一个consumer,分区2、5、8给一个consumer
-
sticky策略:在rebalance的时候,需要保证如下两个原则。
- 分区的分配要尽可能均匀。
- 分区的分配尽可能与上次分配的保持相同。
14、HW和LEO
对于leader新写入的消息,consumer不能立刻消费,leader会等待该消息被所有ISR中的replicas同步后更新HW。
- HW代表新写入的消息还未同步之前的位置。
- LEO代表某个副本当前同步到的最后的位置。
15、 follower如何与leader同步数据?
Kafka的复制机制既不是完全的同步复制,也不是单纯的异步复制。完全同步复制要求All Alive Follower都复制完,这条消息才会被认为commit,这种复制方式极大的影响了吞吐率。而异步复制方式下,Follower异步的从Leader复制数据,数据只要被Leader写入log就被认为已经commit,这种情况下,如果leader挂掉,会丢失数据,kafka使用ISR的方式很好的均衡了确保数据不丢失以及吞吐率。Follower可以批量的从Leader复制数据,而且Leader充分利用磁盘顺序读以及send file(zero copy)机制,这样极大的提高复制性能,内部批量写磁盘,大幅减少了Follower与Leader的消息量差。
16、如何防止消息丢失?
- 不要使用 producer.send(msg),而要使用 producer.send(msg, callback)。记住,一定要使用带有回调通知的 send 方法。
- 设置 acks = all。acks 是 Producer 的一个参数,代表了你对“已提交”消息的定义。如果设置成 all,则表明所有副本 Broker 都要接收到消息,该消息才算是“已提交”。这是最高等级的“已提交”定义。
- 设置 retries 为一个较大的值。这里的 retries 同样是 Producer 的参数,对应前面提到的 Producer 自动重试。当出现网络的瞬时抖动时,消息发送可能会失败,此时配置了 retries > 0 的 Producer 能够自动重试消息发送,避免消息丢失。
- 设置 unclean.leader.election.enable = false。这是 Broker 端的参数,它控制的是哪些 Broker 有资格竞选分区的 Leader。如果一个 Broker 落后原先的 Leader 太多,那么它一旦成为新的 Leader,必然会造成消息的丢失。故一般都要将该参数设置成 false,即不允许非ISR中的副本被选举为leader,以避免数据丢失。
- 设置 replication.factor >= 3。这也是 Broker 端的参数。其实这里想表述的是,最好将消息多保存几份,毕竟目前防止消息丢失的主要机制就是冗余。
- 设置 min.insync.replicas > 1。这依然是 Broker 端参数,控制的是消息至少要被写入到多少个副本才算是“已提交”。设置成大于 1 可以提升消息持久性。在实际环境中千万不要使用默认值 1。
- 确保 replication.factor > min.insync.replicas。如果两者相等,那么只要有一个副本挂机,整个分区就无法正常工作了。我们不仅要改善消息的持久性,防止数据丢失,还要在不降低可用性的基础上完成。推荐设置成 replication.factor = min.insync.replicas + 1。
- 确保消息消费完成再提交。Consumer 端有个参数 enable.auto.commit,最好把它设置成 false,并采用手动提交位移的方式。就像前面说的,这对于单 Consumer 多线程处理的场景而言是至关重要的。
17、如何防止重复消费?
消息重复消费的根本原因都在于:已经消费了数据,但是offset没有成功提交。其中很大一部分原因在于发生了再均衡。
1)消费者宕机、重启等。导致消息已经消费但是没有提交offset。
2)消费者使用自动提交offset,但当还没有提交的时候,有新的消费者加入或者移除,发生了rebalance。再次消费的时候,消费者会根据提交的偏移量来,于是重复消费了数据。
3)消息处理耗时,或者消费者拉取的消息量太多,处理耗时,超过了max.poll.interval.ms的配置时间,导致认为当前消费者已经死掉,触发再均衡。
如何防止:
1)联合主键
2)缓存消费过的消息id
3)分布式锁
18、消息积压问题
消费者消费速度跟不上生产者生产的速度,导致大量消息没有被消费。
解决方案:
1)多线程。
2)创建多个消费组、多个消费者。


浙公网安备 33010602011771号