kafka的作用
- 在0.10版本之前, Kafka仅仅作为一个消息系统,主要用来解决应用解耦、 异步消息、 流量削峰等 问题
- 在0.10版本之后, Kafka提供了连接器与流处理的能力,它也从分布式的消息系统逐渐成为 一个流式的数据平台
kafka的作为流式数据平台的特点
流式数据平台的3个特点
- 类似消息系统,提供事件流的发布和订阅,即具备数据注入功能
- 存储事件流数据的节点具有故障容错的特点,即具备数据存储功能
- 能够对实时的事件流进行流式地处理和分析,即具备流处理功能
-
消息系统 ( 也叫作消息队列)主要有两种消息模型:队列和发布订 阅 。 Kafka使用消费组( consumer group )统一 了上面两种消息模型 。Kafka使用队列模型时,它可以将处理工作平均分配给消费组中的消费者成员;使用发布订阅模式时,它可以将消息 广播给多个消费组。采用多个消费组结合多个消费者,既可以线性扩展消息的处理能力,也 允许消息被多个消费组订阅
-
队列模式(也叫作点对点模式) 。多个消费者读取消息队列,每条消息只发送给一个消费者
-
发布-订阅模式( pub/sub) 。多个消费者订阅主题,主题的每条记录会发布给所有的消费者

- kafka的独特性 : 传统消息系统的流处理通常只 会处理订阅 动作发生之后才到达的新消息,无法处理订阅之前的历史数据 。 分布式文件存储系统一般存 储静态的历史数据,对历史数据的处理一般采用批处理的方式 。 现有的开源系统很难将这些 系统无缝地整合起来, Kafka则将消息系统、存储系统 、 流处理系统都组合在一起,构成了以 Kafka为中心的流式数据-处理平台 。 它既能处理最新的实时数据,也能处理过去的历史数据 。
分区模型
-
主题 : Kafka集群由多个消息代理服务器( broker server )组成,发布至Kafka集群的每条消息都有一个类 别,用主题(topic)来表示。 通常,不同应用产生不同类型的数据,可以设置不同的主题。 一个主题 一般会有多个消息的订阅者,当生产者发布消息到某个主题时,订阅了这个主题的消费者都可以接收 到生产者写人的新消息
-
分区:Kafka集群为每个主题维护了分布式的分区( partition )日志文件,物理意义上可 以把 主题看作分 区的日志文件( partitioned Jog )。 每个分区都是一个有序的、不可变的记录序列,新的消息会不断追加 到提交日志( commit log )。 分区中的每条消息都会按照 时间顺序分配到一个单调递增的顺序编号, 叫 作偏移量( offset),这个偏移量能够唯一地定位当前分区 中的每一条消息 。
-
分区保证有序性和消费者的负载均衡 :Kafka 以分区作为最小的粒度,将每个分区分配给消费组中不同的而且是唯一的消费者,并确保一个分区只 属于一个消费者, 即这个消费者就是这个分区的唯一读取线程 。 那么,只要分区的消息是有序的,消 费者处理的消息顺序就有保证 。 每个主题有多个分区,不同的消费者处理不同的分区,所以 Kafka不 仅保证了消息的有序性,也保证了消费者的负载均衡 。
-
消费模型:消息的消费模型有两种:推送模型(push) 和拉取模型(pull)
- 基于推送模型的消息系统的缺点:基于推送模型的消息系统,由消息代理记录消费者的消费状态。 消息代理在将消 息推送到消费者后 , 标记这条消息为已消费,但这种方式无法很好地保证消息的处理语义 。 比如,消 息代理把消息发送出去后,当消费进程挂掉或者由于网络原因没有收到这条消息时,就有可能造成消 息丢失(因为消息代理已经把这条消息标记为己消费了,但实际上这条消息并没有被实际处理)。 如果 要保证消息的处理语义,消息代理发送完消息后,要设置状态为“已发送”,只有收到消费者的确认请 求后才更新为“已消费”,这就需要在消息代理中记录所有消息的消费状态,这种做法也是不可取的
- Kafka采用拉取模型,由消费者向己记录消费状态,每个消费者五相独立地顺序读取每个分区的 消息
- kafka消息的有效期: Kafka的做法是生产者发布的所有消息会一直保存在Kafka集群中,不管消息有没有被消费。 用户 可以通过设置保留时间来清理过期的数据,比如 , 设置保留策略为两天 。 那么,在消息发布之后,它 可以被不同的消费者消费,在两天之后,过期的消息就会向动清理掉
分布式模型
-
Kafka集群服务端的负载均衡 : Kafka每个主题的多个分区日志分布式地存储在 Kafka集群上,同时为了故障容错,每个分区都会 以副本的方式复制到多个消息代理节点上 。 其中一个节点会作为主副本( Leader),其他节点作为备份 副本( Follower,也叫作从副本)。 主副本会负责所有的客户端读写操作,备份副本仅仅从主副本同步 数据 。 当主副本 出现故障时,备份副本中的一个副本会被选择为新的主副本 。 因为每个分区的副本中 只有主副本接受读写,所以每个服务端都会作为某些分区的主副本,以及另外一些分区的备份副本 , 这样 Kafka集群的所有服务端整体上对客户端是负载均衡 的
-
kafka生产消息的负载均衡 : Kafka的生产者和|消费者相对于服务端而言都是客户端,生产者客户端发布消息到服务端的指定 主题, 会指定消息所属的分区。 生产者发布消息时根据消息是否有键, 采用不同的分区策略。 消息没 有键时,通过轮询方式进行客户端负载均衡 ·消息有键时,根据分区语义确保相同键的消息总是发送 到同一个分区
-
kafka 消费客户端的负载均衡 : Kafka的消费者通过订阅主题来消费消息 并且每个消费者都会设置一个消费组名称 。 因为生产 者发布到主题的每一条消息都只会发送给消费组的一个消费者 。所以,如果要实现传统消息系统的“队 列”模型,可以让每个消费者都拥有相同的消费组名称,这样消息就会负载均衡到所有的消费者;如 果要实现“发布-订阅”模型, 则每个消费者的消费组名称都不相同,这样每条消息就会广播给所有 的消费者
-
增加服务器节点会 提升集群的性能,增加消费者数量会提升处理性能。
-
kafka的消费组管理协议及再平衡操作:同一个消费组下多个消费者互相协调消费工作, Kafka会将所有的分区平均地分配给所有的消费 者实例,这样每个消费者都可以分配到数量均等的分区 。 Kafka的消费组管理协议会动态地维护消费 组的成员列表,当一个新消费者加入消费组,或者有消费者离开消费组,都会触发再平衡操作
如何利用操作系统的优化技术来高效地持久化日 志文件和加快数据传输效率 ?
- 持久化日志文件优化: 预读、后写 、 磁盘缓存
- 零拷贝技术”( zero-copy ) : 结合Kafka的消息有多个订阅者的使用场景,生产者发布的消息一般会被不同的消费者消费多次,只需将磁盘文件的数据复制到页面缓存中 一 次, 然后将数据从页面缓存直接发送到网络中(发送给不同的使用者时,都可以重复使用同一个页面缓 存),避免了重复的复制操作。 这样,消息使用的速度基本上等同于网络连接的速度了
生产者和消费者优化
-
生产者发送消息给分区主副本消息代理节点: Kafka的生产者将消息直接发送给分区主副本所在的消息代理节点,并不需要经过任何的中间路 由层。 为了做到这一点,所有消息代理节点都会保存一份相同的元数据,这份元数据记录了每个主题 分区对应的主副本节点。 生产者客户端在发送消息之前,会向任意一个代理节点请求元数据,井确定 每条消息对应的目标节点 然后把消息直接发送给对应的目标节点
-
生产者客户端有两种方式决定发布的消息归属于哪个分区:通过随机方式将请求负 载到不同的消息、 对于分区语义, Kafka暴露了一个接口,允许用户指定消息的键如何参与分区 。 比如,我们可以将用户编号作为消息的键,因为对相同用户编号散列后的值是幂等的,所以对应的分 区也是幂等的 。
-
消费者读取消息、有两种方式
-
推送模型 : 第一种是消息代理主动地“推送”消息、给下游的消费 者,由消息代理控制数据传输的速率,但是消息代理对下游消费者是否能及时处理不得 而知。 如果数据的消费速率低于产生速率,消费者会处于超负荷状态,那么发送给消费者的消息就会 堆积得越来越多。 而且,推送方式也难以应付不同类型的消费者,因为不同消费者的消费速率不一定都相同,消息代理需要调整不同消费者的传输速率,并让每个消费者充分利用系统的资源。这种方式实现起来比较困难。
-
拉取模型: 读取方式是消费者从消息代理主动地“拉取”数据(见图 1-9右图),消息代理是无状态的, 它不需要标记哪些消息被消费者处理过,也不需要保证一条消息只会被一个消费者处理。 而且,不同 的消费者可以按照向己最大的处理能力来拉取数据,即使有时候某个消费者的处理速度稍微落后,它 也不会影 响其他的消费者,并且在这个消费者恢复处理速度后,仍然可以追赶之前落后的数据
-
拉取模型的缺点: 如果消息代理没有数据或者数据量很少,消费者可能需要不断地轮询,并等待新数 据的到来(拉取模式主动权在消费者手里,但是消费者并不知道消息代理有没有新的数据;如果是推 送模式,只有新数据产生时,消息代理才会发送数据给消费者,就不存在这种问题)。 解决这个问题 的方案是:允许消费者的拉取请求以阻塞式、长轮询的方式等待,直到有新的数据到来。 我们可以为 消费者客户端设置“指定的字节数量”,表示消息代理在还没有收集足够的数据时,客户端的拉取请 求就不会立即返回
副本机制和容错机制
- 副本机制:Kafka的副本机制会在多个服务端节点(简称节点 即消息代理节点 )上对每个主题分区的日志 进行复制。当集群中的某个节点出现故障时,访问故障节点的请求会被转移到其他正常节点的副本上。 副本的单位是主题的分区, Kafka每个主题的每个分区都有一个主副本以及0个或多个备份副本。 备份 副本会保持和主副本的数据同步,用来在主副本失效时替换为主副本
- 分布式系统故障容错需要实时地知道节点是否处于存活状态。存活状态的定义
有两个条件:
- 节点必须和ZK保持会话;
- 如果这个节点是某个分区的备份副本,它必须对分区主副本的写操作进行复制,并且复制的 进度不能落后太多
正在同步中的备份副 本节点( In Sync Replicas,即ISR): 每个分区的主副本会跟踪正在同步中的备份副 本节点( In Sync Replicas,即ISR)。 如果一个备份副本挂掉、没有响应或者落后太多,主副本就会将 其从同步副本集合中移除 。 反之,如果备份副本重新赶上主副本,它就会加入到主副本的 同步集合中 。 在Kafka中, 一条消息只有被ISR集合的所有副本都运用到本地的日志文件,才会认为消息被成功 提交了 。 任何时刻,只要ISR至少有一个副本是存活的, Kafka就可以保证“→条消息一旦被提交,就 不会丢失” 。 只有已经提交的消息才能被消费者消费,因此消费者不用担心会看到因为主副本失败而 丢失的消息 。