kafka流式数据平台
流式数据平台的3个特点:
1.类似消息系统,提供事件流的发布和订阅,具备数据注入功能
2.存储事件流数据的节点具有故障容错的特点,即具备数据处理功能
3.能够对实时的事件流进行流式地处理和分析,即具备流处理能力
kafka如何实现上述3个特点:
1.消息系统:kafka通过消费组实现队列+发布订阅这两种消息模型。
队列模式:kafka可以将处理工作平均分配给消费组中的消费者成员
发布订阅模式:将消息广播给多个消费组。采用多个消费组结合多个消费者,既可以线性扩展消息的处理能力,也允许消息被多个消费组订阅。
2.队列模式(点对点模式):多个消费者读取消息队列,每条消息只发送给一个消费者
3.发布-订阅模式。多个消费者订阅主题,主题的每条记录会发布给所有的消费者。
4.存储系统:数据写入到kafka集群的服务器节点时,还会复制多份来保证出现故障时仍能可用。为了保证消息的可靠存储,kafka还允许生产者的生产请求在收到应答结果之前,阻塞式地等待一条消息,直到它完全地复制到多个节点上,才认为这条消息写入成功。
5.流处理系统:kafka流处理为开发者提供完整的流处理API,比如流的聚合、连接、各种转换操作。同时,Kafka流处理框架内部解决很多流处理应用程序都会面临的问题:处理乱序或迟来的数据、重新处理输入数据,窗口和状态操作等。
6.将消息系统、存储系统、流处理系统组合在一起:Kafka构成了以kafka为中心的流式数据处理平台。它既能处理最新的实时数据,也能处理过去的历史数据。kafka作为流式数据平台的核心组件,主要包括下面4种核心API
生产者:应用程序发布事件流到kafka的一个或多个主题。
消费者:应用程序订阅kafka的一个或多个主题,并处理事件流
连接器:将kafka主题和已有的数据源进行连接,数据可以互相导入和导出
流处理:从kafka主题消费输入流,经过处理后,产生输出流到输出主题。
kafka的基本概念
1.kafka的主题与分区内部是如何实现的,它有什么特点?
kafka集群由多个消息代理服务器(broker server)组成,发布到kafka群的每条消息都有一个类别,用主题(topic)来表示。
kafka集群为每个主题维护了分布式的分区日志文件,物理意义上可以把主题看做分区的日志文件。每个分区都是一个有序的不可变的记录许兰,新的消息会不断追加到提交日志。
2.与传统的消息系统相比,kafka的消费模型有什么优点?
传统消息系统在服务端保持消息的顺序,这就意味着在并行消费时,传统消息系统无法很好第保证消息被顺序处理。虽然可以设置一个专用的消费者只消费一个队列, 以此来解决消费顺序的问题,但是这就使得消费处理无法真正执行。
kafka已分区作为最小的粒度,将每个分区分配给消费组中不同的而且是唯一的消费者,这个消费者就是这个分区的唯一读取线程。只要分区的消息是有序的,消费者处理的消息顺序就有保障。每个祖逖有多个分区,不同的消费者处理不同的分区,所以kafka不仅保证了消息的有序性,也做到了消费者的负载均衡。
3.kafka如何实现分布式的数据存储和数据读取?
kafka采用拉取模型,由消费者自己记录消费状态,每个消费者户型独立地顺序读取每个分区的消息。消费者拉取的最大上限通过最高水位控制,生产者最新写入的消息如果还没有达到备份数量,对消费者是不可见的。这种由消费者控制偏移量的优点是:消费者可以按照任意的顺序消费信息。
4.kafka如何保证消息系统的整体吞吐量和处理延迟?
有些消息系统,消息代理会在消息被消费后立即删除消息,如果有不同类型的消费者订阅同一个主题,消息代理可能需要冗余地存储同一条消息;或者等所有消费者都消费完才删除,这就需要消息代理跟踪每个消费者的消费状态,这种设计很大程度上限制了消息系统的整体吞吐量和处理延迟。
kafka的做法是生产者发布的所有消息会一直保存在kafka集群中,不管消息有没有被消费。用户可以通过设置保留时间来清理过期的数据。
分区模型
kafka集群由多个消息代理服务器(broker server)组成,发布到kafka群的每条消息都有一个类别,用主题(topic)来表示。
kafka集群为每个主题维护了分布式的分区日志文件,物理意义上可以把主题看做分区的日志文件。每个分区都是一个有序的不可变的记录许兰,新的消息会不断追加到提交日志。
传统消息系统在服务端保持消息的顺序,这就意味着在并行消费时,传统消息系统无法很好第保证消息被顺序处理。虽然可以设置一个专用的消费者只消费一个队列, 以此来解决消费顺序的问题,但是这就使得消费处理无法真正执行。
kafka比传统消息系统有更强的顺序性保证,它使用主题的分区作为消息粗粒的并行单元。kafka已分区作为最小的粒度,将每个分区分配给消费组中不同的而且是唯一的消费者,这个消费者就是这个分区的唯一读取线程。只要分区的消息是有序的,消费者处理的消息顺序就有保障。每个祖逖有多个分区,不同的消费者处理不同的分区,所以kafka不仅保证了消息的有序性,也做到了消费者的负载均衡。
消费模型
分布式模型
消费模型有两种:推送模型和拉取模型
基于推送模型的消息系统,由消息代理记录消费者的消费模式,这种方法无法很好地保证消息的处理语义。例如,消息代理把消息发出去后,当消费进程挂掉或者由于网络原因没有收到这条消息,就有可能造成消息丢失。如果要保证消息的处理语义,消息代理发送完消息之后,要设置状态为“已发送”,只有手动消费者的确认请求后才更新为已消费。
kafka采用拉取模型,由消费者自己记录消费状态,每个消费者户型独立地顺序读取每个分区的消息。消费者拉取的最大上限通过最高水位控制,生产者最新写入的消息如果还没有达到备份数量,对消费者是不可见的。这种由消费者控制偏移量的优点是:消费者可以按照任意的顺序消费信息。
有些消息系统,消息代理会在消息被消费后立即删除消息,如果有不同类型的消费者订阅同一个主题,消息代理可能需要冗余地存储同一条消息;或者等所有消费者都消费完才删除,这就需要消息代理跟踪每个消费者的消费状态,这种设计很大程度上限制了消息系统的整体吞吐量和处理延迟。
kafka的做法是生产者发布的所有消息会一直保存在kafka集群中,不管消息有没有被消费。用户可以通过设置保留时间来清理过期的数据。
分布式模型
kafka每个主题的多个分区日志分布式地存储在kafka集群上,同时为了故障容错,每个分区都会以副本的方式复制到多个消息代理节点上。其中一个节点会作为主副本,其他节点作为备份副本。主副本负责所有的客户端读写操作,备份副本仅仅从主副本同步数据。当主副本出现故障时,备份副本中的一个副本会被选择为新的主副本。这样kafka机器的所有服务端整体上对客户端是负载均衡的。
生产者发布消息到服务端指定的主题,根据消息是否有键,采用不同的分区策略。消息没有键,通过轮询方式进行客户端负载均衡;消息有键,根据分区语义确保相同键的消息总是发送到同一个分区。
kafka的消费者通过订阅主题来消费消息,并且每个消费者都会设置一个消费组名称。如果要实现传统消息系统的队列模型,可以让没有消费者都拥有相同的消费组名称,这样消息就会负载均衡到所有的消费者,如果要实现发布-订阅模型,每个消费者的消费组名称都不相同,这样每条消息就会广播给所有的消费组。
同一个消费组下多个消费者相互协调消费工作,kafka会将所有的分区平均地分配给所有的消费组实例,这样每个消费者都可以分配到数量均等的分区。kafka的消费组管理协议会动态地维护消费组的成员列表。
如果业务上需要保证所有消息完全一致,只能通过设置一个分区完成,但这种做法的缺点是最多只有一个消费者进行消费。一般来说,只需要保证每个分区的有序性,再对消息加上键来保证相同键的所有消息落入同一个分区,就可以满足绝大多数的应用。
kafka的设计与实现
1.如何利用操作系统的优化技术来高效地持久化日志文件和加快数据传输效率?
预读、后写、零拷贝
2.kafka的生产者如何批量地发送消息,消费者采用来取模型带来的优点有哪些?
生产者会尝试在内存中搜集足够数据,并在一个请求中一次性发送一批数据。
3.kafka的副本机制如何工作,当故障发生时,怎么确保数据不丢失?
文件系统的持久化与数据传输效率
预读会提前将一个比较大的磁盘块读入内存。
后写会将很多小的逻辑操作合并起来组合成一个大的物理写操作
操作系统还会将主内存剩余的所有空闲内存空间都用作磁盘缓存。
数据的传输效率决定了生产者和消费者的性能。消息系统内的消息从生产者保存 到服务端,消费者再从服务端读取出来,数据的传输效率决定了生产者和消费者的性能。如果我们能够将多条消息按照分区进行分组,并采用批量的方式一次发送一个消息集,并且对消息集进行压缩,就可以减少网络传输的带宽,进一步提高数据的传输效率。
传统读取磁盘文件的数据在每次发送到网络时,都需要将页面缓存先保存到用户缓存,然后在读取消息时再将其复制到内核空间,具体步骤如下。
1)操作系统将磁盘数据从磁盘中读取文件到内核空间里的页面缓存。
2)应用程序将数据从内核空间读入用户空间的缓冲区
3)应用程序将读到的数据写回内核空间并放入socket缓冲区
4)操作系统将数据从socket缓冲区复制到网卡接口,此时数据才能通过网络发送出去。
使用零拷贝技术只需将磁盘文件的数据复制到页面缓存中一次,然后将数据从页面缓存直接发送到网络中,避免了重复的赋值操作。这样,消息使用的速度基本上等同于网络连接的速度。
生产者与消费者
kafka的生产者将消息直接发送给分区主副本所在的消息代理节点,并不需要经过任何的中间路由层。为了做的这一点,所有消息代理节点都会保存一份相同的元数据,记录每个主题分区对应的主副本节点。
生产者客户端有两种方式决定发布的消息归属哪个分区:1.通过随机方式将请求负载到不同的消息代理节点,2.使用分区语义函数将向提供键的所有消息发布到同一个分区
生产者采用批量发送消息集的方式解决了网络请求过多的问题。生产者会尝试在内存中搜集足够数据,并在一个请求中一次性发送一批数据。客户端采用这种缓冲机制,在发送消息前会手机尽可能多的数据,通过每次牺牲一点点额外的延迟来换取更高的吞吐量。
kafka采用基于拉取模型的消费状态处理,它将主题分成多个有序的分区,任何时刻每个分区都纸杯一个消费者使用。并且,消费者会记录每个分区的消费进度(偏移量),不需要记录每条消息的状态。kafka的消费者会定时地将分区的消费进度保存成检查点文件,表示“这个位置之前的消息都已经被消费过了”。这样做的好处:消费者可以故意回退到某个旧的偏移量位置,然后重新处理数据。
和生产者采用批量发送消息类似,消费者拉取消息也可以一次拉取一批消息。消费者客户端拉取消息这个过程一般套在一个死循环里,表示消费者永远处于消费消息的状态。
消费者采用拉取方式消费消息有一个缺点:如果消息代理没有数据或者数据量很少,消费者可能需要不断地轮询,并等等新数据的到来。解决方案:允许消费者的拉取请求以阻塞式、长轮询的方式等待,知道有新的数据到来。我们可以为消费者客户端设置“指定的字节数量”,表示消息代理在还没有搜集足够的数据时,客户端的拉取请求就不会立即返回。
副本机制和容错处理
kafka对节点的存活定义有两个条件:
1.节点必须和ZK保持会话
2.如果这个节点是某个分区的备份副本,它必须对分区主副本的写操作进行复制,并且复制的进度不能落后太多。
满足这两个条件,叫做“正在同步中”。每个分区的主副本会跟踪正在同步总的备份副本节点(ISR)。
kafka的消息提交机制如何保证消费者看到的数据是一致的?
kafka保证“一条消息一旦被提交,就不会丢失”。只有已经提交的消息才能被消费者消费,因此消费者不用担心会看到因为主副本失败而丢失的消息。例如:生产者发布了10条消息,这10条消息已经写入主副本且成功地复制到ISR的所有副本后,他们才被认为是提交的。