kafka消息队列

在现有的工程项目中,经常需要对用户的实时log进行处理,实时log主要是通过kafka进行记录,分两个部分,一部分通过kafka进行切片后存储在hdfs中,另一部分也可以提供实时的kafka数据,方便实时的处理。

消息队列:

消息队列技术是分布式应用间交换信息的一种技术。消息队列可驻留在内存或磁盘上, 队列存储消息直到它们被应用程序读走。通过消息队列,应用程序可独立地执行--它们不需要知道彼此的位置、或在继续执行前不需要等待接收程序接收此消息。在分布式计算环境中,为了集成分布式应用,开发者需要对异构网络环境下的分布式应用提供有效的通信手段。为了管理需要共享的信息,对应用提供公共的信息交换机制是重要的。常用的消息队列技术是 Message Queue。

Message Queue 的通讯模式

  1. 点对点通讯:点对点方式是最为传统和常见的通讯方式,它支持一对一、一对多、多对多、多对一等多种配置方式,支持树状、网状等多种拓扑结构。

  2. 多点广播:MQ 适用于不同类型的应用。其中重要的,也是正在发展中的是"多点广播"应用,即能够将消息发送到多个目标站点 (Destination List)。可以使用一条 MQ 指令将单一消息发送到多个目标站点,并确保为每一站点可靠地提供信息。MQ 不仅提供了多点广播的功能,而且还拥有智能消息分发功能,在将一条消息发送到同一系统上的多个用户时,MQ 将消息的一个复制版本和该系统上接收者的名单发送到目标 MQ 系统。目标 MQ 系统在本地复制这些消息,并将它们发送到名单上的队列,从而尽可能减少网络的传输量。

  3. 发布/订阅 (Publish/Subscribe) 模式:发布/订阅功能使消息的分发可以突破目的队列地理指向的限制,使消息按照特定的主题甚至内容进行分发,用户或应用程序可以根据主题或内容接收到所需要的消息。发布/订阅功能使得发送者和接收者之间的耦合关系变得更为松散,发送者不必关心接收者的目的地址,而接收者也不必关心消息的发送地址,而只是根据消息的主题进行消息的收发。

  4. 群集 (Cluster):为了简化点对点通讯模式中的系统配置,MQ 提供 Cluster(群集) 的解决方案。群集类似于一个域 (Domain),群集内部的队列管理器之间通讯时,不需要两两之间建立消息通道,而是采用群集 (Cluster) 通道与其它成员通讯,从而大大简化了系统配置。此外,群集中的队列管理器之间能够自动进行负载均衡,当某一队列管理器出现故障时,其它队列管理器可以接管它的工作,从而大大提高系统的高可靠性。

流媒体平台:

1. 发布和订阅记录流(类似于消息队列,可以突破地理指向限制,不关心目的地址,根据主题或内容进行收发)

2. 以容错的方式存储记录流

3. 在发生记录时处理记录流

Kafka:

被用于两大类的应用程序:

  1. 构建可在系统或应用程序之间可靠获取数据的实时流数据管道
  2. 构建实时流应用程序,可以转换或响应数据流

几个概念:

  • Kafka作为一个或多个服务器上的集群运行。
  • Kafka集群以称为主题的类别存储记录流。
  • 每个记录由一个键,一个值和一个时间戳组成。

Broker:Kafka 集群包含一个或多个服务器,这种服务器被称为 broker。

Topic:每条发布到 Kafka 集群的消息都有一个类别,这个类别被称为 Topic。(物理上不同 Topic 的消息分开存储,逻辑上一个 Topic 的消息虽然保存于一个或多个 broker 上,但用户只需指定消息的 Topic 即可生产或消费数据而不必关心数据存于何处)。

Partition:Partition 是物理上的概念,每个 Topic 包含一个或多个 Partition。

Producer:负责发布消息到 Kafka broker。

Consumer:消息消费者,向 Kafka broker 读取消息的客户端。

Consumer Group:每个 Consumer 属于一个特定的 Consumer Group(可为每个 Consumer 指定 group name,若不指定 group name 则属于默认的 group)。

这是 Kafka 用来实现一个 Topic 消息的广播(发给所有的 Consumer )和单播(发给任意一个 Consumer )的手段。一个 Topic 可以有多个 Consumer Group。Topic 的消息会复制(不是真的复制,是概念上的)到所有的 Consumer Group,但每个 Consumer Group 只会把消息发给该 Consumer Group 中的一个 Consumer。如果要实现广播,只要每个 Consumer 有一个独立的 Consumer Group 就可以了。如果要实现单播只要所有的 Consumer 在同一个 Consumer Group 。用 Consumer Group 还可以将 Consumer 进行自由的分组而不需要多次发送消息到不同的 Topic 。

  • Kafka 交互流程

Kafka 是一个基于分布式的消息发布-订阅系统,它被设计成快速、可扩展的、持久的。与其他消息发布-订阅系统类似,Kafka 在主题当中保存消息的信息。生产者向主题写入数据,消费者从主题读取数据。由于 Kafka 的特性是支持分布式,同时也是基于分布式的,所以主题也是可以在多个节点上被分区和覆盖的。

信息是一个字节数组,程序员可以在这些字节数组中存储任何对象,支持的数据格式包括 String、JSON、Avro。Kafka 通过给每一个消息绑定一个键值的方式来保证生产者可以把所有的消息发送到指定位置。属于某一个消费者群组的消费者订阅了一个主题,通过该订阅消费者可以跨节点地接收所有与该主题相关的消息,每一个消息只会发送给群组中的一个消费者,所有拥有相同键值的消息都会被确保发给这一个消费者。

Kafka 设计中将每一个主题分区当作一个具有顺序排列的日志。同处于一个分区中的消息都被设置了一个唯一的偏移量。Kafka 只会保持跟踪未读消息,一旦消息被置为已读状态,Kafka 就不会再去管理它了。Kafka 的生产者负责在消息队列中对生产出来的消息保证一定时间的占有,消费者负责追踪每一个主题 (可以理解为一个日志通道) 的消息并及时获取它们。基于这样的设计,Kafka 可以在消息队列中保存大量的开销很小的数据,并且支持大量的消费者订阅。

分配

日志的分区分布在Kafka集群中的服务器上,每个服务器处理数据和请求共享分区。每个分区都通过可配置数量的服务器进行复制,以实现容错。

每个分区有一个服务器充当“领导者”,零个或多个服务器充当“追随者”。领导处理分区的所有读取和写入请求,而追随者被动地复制领导。如果领导失败,其中一个追随者将自动成为新领导。每个服务器充当其中一些分区的领导者和其他人的追随者,因此负载在集群内平衡良好。

生产者

生产者发布数据到他们选择的主题。生产者负责选择哪个记录分配给主题内的哪个分区。这可以以循环的方式完成,只是为了平衡负载,或者可以根据某些语义分区功能(例如基于记录中的某个键)来完成。更多关于使用分区在第二!

消费者

消费者用消费者组名称标记自己,并且发布到主题的每个记录被传递到每个订阅消费者组中的一个消费者实例。消费者实例可以在不同的进程中或在不同的机器上。

如果所有消费者实例具有相同的消费者组,则记录将有效地在消费者实例上进行负载均衡。

如果所有消费者实例具有不同的消费者组,则每个记录将被广播给所有消费者进程。

两个服务器Kafka集群托管四个分区(P0-P3)与两个消费者组。消费者组A有两个消费者实例,而组B有四个消费者实例。

然而,更普遍的是,我们发现话题中有少量消费群体,每个“逻辑用户”都有一个消费群体。每个组由许多消费者实例组成,具有可扩展性和容错性。这不过是发布 - 订阅语义,订阅者是一群消费者而不是一个进程。

在Kafka中实现消费的方式是将日志中的分区划分为消费者实例,以便每个实例在任何时间点都是“公平分享”分区的唯一消费者。这个维护组中成员资格的过程是由Kafka协议动态地处理的。如果新实例加入组,他们将接管来自组中其他成员的一些分区; 如果一个实例死亡,其分区将分配给其余的实例。

卡夫卡只提供一个分区内的记录总数,而不是主题中的不同分区之间。每个分区排序与按键分区数据的能力相结合,足以满足大多数应用程序的需求。但是,如果您需要全部订单而不是记录,则可以通过仅具有一个分区的主题来实现,但这意味着每个消费者组只有一个消费者进程。

消息传输流程

Producer即生产者,向Kafka集群发送消息,在发送消息之前,会对消息进行分类,即Topic,上图展示了两个producer发送了分类为topic1的消息,另外一个发送了topic2的消息。

Topic即主题,通过对消息指定主题可以将消息分类,消费者可以只关注自己需要的Topic中的消息

Consumer即消费者,消费者通过与kafka集群建立长连接的方式,不断地从集群中拉取消息,然后可以对这些消息进行处理。

从上图中就可以看出同一个Topic下的消费者和生产者的数量并不是对应的。

与生产者的交互

 

生产者在向kafka集群发送消息的时候,可以通过指定分区来发送到指定的分区中;也可以通过指定均衡策略来将消息发送到不同的分区中;如果不指定,就会采用默认的随机均衡策略,将消息随机的存储到不同的分区中

与消费者的交互

  

在消费者消费消息时,kafka使用offset来记录当前消费的位置

在kafka的设计中,可以有多个不同的group来同时消费同一个topic下的消息,如图,我们有两个不同的group同时消费,他们的的消费的记录位置offset各不项目,不互相干扰。

对于一个group而言,消费者的数量不应该多余分区的数量,因为在一个group中,每个分区至多只能绑定到一个消费者上,即一个消费者可以消费多个分区,一个分区只能给一个消费者消费;因此,若一个group中的消费者数量大于分区数量的话,多余的消费者将不会收到任何消息。

本质上kafka只支持Topic.每个consumer属于一个consumer group;反过来说,每个group中可以有多个consumer.发送到Topic的消息,只会被订阅此Topic的每个group中的一个consumer消费.

1.如果所有的consumer都具有相同的group,这种情况和queue模式很像;消息将会在consumers之间负载均衡.

2.如果所有的consumer都具有不同的group,那这就是"发布-订阅";消息将会广播给所有的消费者.

Kafka的逻辑数据模型:

生产者发送数据给服务端时,构造的是ProducerRecord<Integer, String>(String topic, Integer key,String value)对象并发送,从这个构造函数可以看到,kafka的表面逻辑数据模型是key-value。当然api再发送前还会在这个基础上加入若干校验信息,不过这个对用户而言是透明的。

Kafka的分发策略:

跟很多分布式多备份系统类似,kafka的基本网络结构如下:

一个节点(Broker)中存有不同partition的备份,一个partition存在多份备份保存在不同节点上并且选举出一个作为leader跟客户端交互,一个topic拥有多个partition。

默认的kafka分发算法是hash(key)%numPartitions,简单来就是哈希再取模。当然这个算法可以自定义,只要重写相关接口。如上图在一个四台主机上创建了一个有两个备份,四个分区partion的主题topic,但生产者需要发送某个key-value对象到消息队列里面时,创建连接时通过访问zookeeper,获取到一份leader partion列表(Broker1. Partition-0, Broker2. Partition1, Broker3. Partition-2, Broker4.Partition-3),再根据分发算法计算出这个对象应该要发送到哪个leader partion中。

Kafka的节点间的数据一致性策略设计:

对于任何多节点多备份的分布式系统而言,数据的一致性问题都是绕不开的难点,一般的选择是要么优先考虑效率,这样可能就造成数据不一致甚至是数据丢失,要么选择保障数据一致性和数据安全性牺牲效率。在kafka的身上也存在这样的矛盾。

Kafka是一种分partion,多节点多备份的分布式系统,每个partion都可以存在多份备份,每个备份在不同的节点上。多个备份中会根据zookpeer的注册信息通过算法选举出其中一份作为leader,这个leader负责和客户端的读写访问进行交互。其他备份不参与跟客户端的交互。而是去跟leader partion交互同步数据。这样一来就可能出现主备之间数据不一致的情况。Kafka在客户端提供了一个配置选项props.put("acks", "all");--其中all表示生产者等待确认所有的备份数据都写入pagecache后再返回。可以设置为0(不等待任何确认),1(leader确认)或者其他小于备份数的数字。其他备份节点会异步去同步leader partion的数据,保持一致,当然如果在同步的过程中,leader partion出现数据丢失,那么这部分数据将永远丢失。

Kafka的备份和负载均衡:

Kafka的备份很明显,上文已经说过是通过讨论一致性问题已经交待清楚,至于Kafka的负载均衡,个人发现是严重依赖于zookeeper上的注册信息,通过一套算法来选取leader partion来实现kafka多节点的负载均衡。Zookeeper中保存了kafka几乎一切的重要信息,比如topic,每个topic下面的多个partion信息,主机节点信息(包括ip和端口),每个节点下的多个partion信息,每个partion的主备份信息,消费客户端的group_id分组信息,每个消费者信息等。通过这一堆信息进行算法计算最后得出负载均衡的方案,主要体现是选出让kafka效率性能达到最好的每个partion的leader。并且在zookeeper中注册监视器,一旦发现上述信息有变动则更新负载均衡方案。

Kafka 高吞吐量的秘诀

消息中间件从功能上看就是写入数据、读取数据两大类,优化也可以从这两方面来看。

为了优化写入速度 Kafak 采用以下技术:

1. 顺序写入
磁盘大多数都还是机械结构(SSD不在讨论的范围内),如果将消息以随机写的方式存入磁盘,就需要按柱面、磁头、扇区的方式寻址,缓慢的机械运动(相对内存)会消耗大量时间,导致磁盘的写入速度与内存写入速度差好几个数量级。为了规避随机写带来的时间消耗,Kafka 采取了顺序写的方式存储数据,如下图所示:

每条消息都被append 到该 partition 中,属于顺序写磁盘,因此效率非常高。

每个分区是一个有序的,不可变的记录序列,不断追加到结构化的提交日志中。分区中的记录每个分配一个连续的id号,称为偏移量,用于唯一标识分区内的每条记录。

Kafka集群使用可配置的保留期限来保留所有已发布的记录(无论是否已被使用)。例如,如果保留策略设置为两天,则在记录发布后的两天内,保留策略可供使用,之后将被丢弃以腾出空间。卡夫卡的性能在数据大小方面是有效的,所以长时间存储数据不成问题。

Kafka的物理存储模型和查找数据的设计:

Kafka的物理存储模型比较简单,在kafka的物理持久化的存储中有分Segment的概念,每个Segment有两种类型的文件:索引文件.index和日志文件(数据文件).log。两者的命名规则都是以这个Segment的第一条的消息逻辑偏移量作为文件名。索引是稀疏索引,目的在于减少索引文件的数据量,其文件的内容是key-value结构,key是消息的偏移量offeset(就是一个自增的序列号),value是对应的log文件的实际物理磁盘偏移量。

值得一提的是,跟其他正常分布式不一样,kafka并不支持根据给定的key查找该key对应的value值的能力,某种意义而言,逻辑数据模型中的key只是用来实现分发计算用的,所以使用kafka查找数据只能以指定消息的偏移量的放松实现。

整个查找过程:当要查找offset=888及后续的消息时,kafka先到该节点上找到对应的Segment。通过该Segment的index文件上用二分查找的方法找到最接近offset=888的纪录,比如886,然后找到886对应的物理磁盘偏移量999,这样就从log的磁盘偏移量找起,连续遍历了两个消息后就能找到888这个消息的数据(log文件中保留了每条消息的逻辑偏移量,长度和数据)。

实际上,以消费者为单位保留的唯一元数据是消费者在日志中的偏移或位置。这个偏移量是由消费者控制的:消费者通常会在读取记录时线性地推进其偏移量,但事实上,由于消费者的位置是由消费者控制的,所以它可以以任何喜欢的顺序消费记录。例如,消费者可以重置为较旧的偏移量以重新处理来自过去的数据,或者跳至最近的记录并从“now”开始消费。

这些功能的组合意味着卡夫卡的消费者非常便宜 - 他们可以来来去去,对集群或其他消费者没有太大的影响。例如,您可以使用我们的命令行工具来“尾巴”任何主题的内容,而不会改变现有的使用者所使用的内容。

日志中的分区有几个用途。首先,它们允许日志的大小超出适合单个服务器的大小。每个单独的分区必须适合托管它的服务器,但是一个主题可能有许多分区,因此它可以处理任意数量的数据。其次,它们作为并行的单位 - 更多的是在一点上。

但这种方法有一个缺陷:没有办法删除数据。所以Kafka是不会删除数据的,它会把所有的数据都保留下来,每个消费者(Consumer)对每个 Topic 都有一个offset 用来表示读取到了第几条数据。

上图中有两个消费者,Consumer1 有两个 offset 分别对应 Partition0、Partition1(假设每一个 Topic 一个 Partition )。Consumer2 有一个 offset 对应Partition2 。这个 offset 是由客户端 SDK 保存的,Kafka 的 Broker 完全无视这个东西的存在,一般情况下 SDK 会把它保存到 zookeeper 里面。
如果不删除消息,硬盘肯定会被撑满,所以 Kakfa 提供了两种策略来删除数据。一是基于时间,二是基于 partition 文件大小,具体配置可以参看它的配置文档。
即使是顺序写,过于频繁的大量小 I/O 操作一样会造成磁盘的瓶颈,所以 Kakfa 在此处的处理是把这些消息集合在一起批量发送,这样减少对磁盘 I/O 的过度操作,而不是一次发送单个消息。
2. 内存映射文件
即便是顺序写入硬盘,硬盘的访问速度还是不可能追上内存。所以 Kafka 的数据并不是实时的写入硬盘,它充分利用了现代操作系统分页存储来利用内存提高I/O效率。Memory Mapped Files (后面简称mmap)也被翻译成内存映射文件,在64位操作系统中一般可以表示 20G 的数据文件,它的工作原理是直接利用操作系统的 Page 来实现文件到物理内存的直接映射。完成映射之后对物理内存的操作会被同步到硬盘上(由操作系统在适当的时候)。
通过 mmap 进程像读写硬盘一样读写内存,也不必关心内存的大小,有虚拟内存为我们兜底。使用这种方式可以获取很大的 I/O 提升,因为它省去了用户空间到内核空间复制的开销(调用文件的 read 函数会把数据先放到内核空间的内存中,然后再复制到用户空间的内存中)
但这样也有一个很明显的缺陷——不可靠,写到 mmap 中的数据并没有被真正的写到硬盘,操作系统会在程序主动调用 flush 的时候才把数据真正的写到硬盘。所以 Kafka 提供了一个参数—— producer.type 来控制是不是主动 flush,如果Kafka 写入到 mmap 之后就立即 flush 然后再返回 Producer 叫同步(sync);如果写入 mmap 之后立即返回,Producer 不调用 flush ,就叫异步(async)。
3. 标准化二进制消息格式
为了避免无效率的字节复制,尤其是在负载比较高的情况下影响是显著的。为了避免这种情况,Kafka 采用由 Producer,Broker 和 Consumer 共享的标准化二进制消息格式,这样数据块就可以在它们之间自由传输,无需转换,降低了字节复制的成本开销。

而在读取速度的优化上 Kafak 采取的主要是零拷贝

零拷贝(Zero Copy)的技术:
传统模式下我们从硬盘读取一个文件是这样的

(1)操作系统将数据从磁盘读到内核空间的页缓存区
(2)应用将数据从内核空间读到用户空间的缓存中
(3)应用将数据写会内核空间的套接字缓存中
(4)操作系统将数据从套接字缓存写到网卡缓存中,以便将数据经网络发出
这样做明显是低效的,这里有四次拷贝,两次系统调用。
针对这种情况 Unix 操作系统提供了一个优化的路径,用于将数据从页缓存区传输到 socket。在 Linux 中,是通过 sendfile 系统调用来完成的。Java提供了访问这个系统调用的方法:FileChannel.transferTo API。这种方式只需要一次拷贝:操作系统将数据直接从页缓存发送到网络上,在这个优化的路径中,只有最后一步将数据拷贝到网卡缓存中是需要的。

零拷贝方式传输到 Socket:

Kafka的持久化策略设计:

Kafka的持久化设计是非常有特色的,和其他分布式系统不同,它没有自己维护一套缓存机制,而是直接使用了操作系统的文件系统(操作系统的文件系统自带pagecache)。这样的好处是减少了一次内存拷贝的消耗。其他分布式系统比如cassandra,自己在服务端维护了一份数据缓冲内存块datacache,当需要持久化时再调用操作系统的文件系统写入到文件中,这样就多了一次datacache到pagecache的拷贝消耗。这样的话,kafka的持久化管理关键是管理文件系统的pagecache的刷盘。

由于kafka采用了这种特别的持久化策略,所以在kafka中并没有其他分布式系统的重做日志。所以kafka在出现故障后的数据恢复策略有自己的一套:首先,kafka会通过配置文件配置pagecache定时或者定量刷盘的频率以保证即使出现故障也能把丢失的数据降低到最少。其次,pageche本身是操作系统管理维护的,跟kafka自身的服务进程没有关系,如果是kafka本身挂了的话,重启后还是能访问到pageche中的数据的。最后如果很不幸是kafka所在的一个节点的主机挂掉的话,那么重启主机和kafka后也可以从其他备份节点重新同步丢失的数据。

Kafka高性能的和持久化策略关系非常密切,这部分内容,也是整个kafka设计的精髓所在:

传统的观念认为磁盘的读写是非常低效的,所以一般系统都会自己管理一块内存datacache充当磁盘的缓存,只有需要的时候才去和磁盘交互。但是实际上,磁盘的低效的原因不在于磁盘io,而在于磁头的随机寻址。如果数据是顺序读写的话(也就是一次磁头寻址,连续io),其实速度是非常快的((Raid-5,7200rpm):顺序 I/O: 600MB/s)。而在传统的设计中虽然加入了内存作为缓存,但是为了保证数据的安全性还是得提供一份重做日志(每次的修改操作都要记录在重做日志redo.log中,以保证内存丢失后能根据重做日志进行恢复),并且当datacache里面的数据达到一定容量时刷新到磁盘的data文件中。但是kafka并没有使用这套常规设计,并没有自己维护一套datacache而是另辟蹊径,直接使用操作系统中的文件系统,并利用文件系统原有的pagecache作为数据缓存。减少了datacache到pagecache的拷贝消耗。并且顺序地进行磁盘io,这样大大提高了kafka写数据时持久化的效率。对于kafka的读数据这块,kafka也使用了Sendfile技术来提高读的效率,传统的读方案是读取磁盘的数据到pagecache中,然后从pagecache拷贝一份到用户进程的datacache中,datacache再拷贝到内核的socket缓存区中,最后从socket缓存区拷贝数据到网卡中发送。而Sendfile技术跳过了用户进程的datacache这一环节,直接读取磁盘的数据到pagecache中,然后从pagecache拷贝一份到socket缓存区中,最后从socket缓存区拷贝数据到网卡中发送。整个过程减少了两次拷贝消耗。

卡夫卡作为消息系统

卡夫卡的流概念如何与传统的企业消息传递系统相比较?

消息传统上有两种模式:排队发布 - 订阅。在队列中,消费者池可以从服务器读取并且每个记录都转到其中的一个; 在发布 - 订阅记录被广播给所有消费者。这两种模式都有其优点和缺点。排队的优势在于它允许您将数据处理划分为多个消费者实例,这样可以扩展处理。不幸的是,队列不是多用户的,一旦一个进程读取了数据,发布 - 订阅允许您将数据广播到多个进程,但无法进行扩展处理,因为每条消息都发送给每个订阅者。

卡夫卡的消费群体概念概括了这两个概念。与队列一样,消费者组允许您将一系列流程(消费者组的成员)的处理分开。与发布 - 订阅一样,Kafka允许您向多个消费者群体广播消息。

Kafka模型的优点是每个主题都具有这些属性 - 它可以扩展处理,也可以是多用户 - 不需要选择其中一个。

Kafka也比传统的消息系统有更强的订单保证。

传统队列在服务器上按顺序保留记录,并且如果多个使用者从队列中消耗,则服务器按照它们存储的顺序来提交记录。但是,虽然服务器按顺序提交记录,但是记录是异步传递给消费者的,所以它们可能会针对不同的消费者而出现故障。这实际上意味着记录的排序在并行消耗的情况下丢失。消息传递系统通常具有“排他消费者”的概念,只允许一个进程从队列中消费,但这当然意味着在处理过程中没有并行性。

卡夫卡做得更好。通过在主题内部具有并行性概念 - 分区概念,Kafka能够提供订单保证和负载平衡。这是通过将主题中的分区分配给使用者组中的使用者来实现的,以便每个分区仅由组中的一个使用者使用。通过这样做,我们确保消费者是该分区的唯一读者,并按顺序使用这些数据。由于有很多分区,这仍然可以平衡许多消费者实例的负载。但请注意,消费群组中的消费者实例不能多于分区。

卡夫卡作为存储系统

任何允许将消息发布出去的消息队列都可以充当存储系统。Kafka的不同之处在于它是一个非常好的存储系统。

写入Kafka的数据写入磁盘并进行复制以实现容错。Kafka允许生产者等待确认,以便在完全复制之前写入不被认为是完整的,并且即使写入的服务器失败也能保证持续。

Kafka的磁盘结构使用了很好的规模 - 无论您在服务器上有50 KB还是50 TB的持久性数据,Kafka都会执行相同的操作。

由于认真考虑存储并允许客户端控制其读取位置,所以可以将Kafka视为专用于高性能,低延迟提交日志存储,复制和传播的专用分布式文件系统。

有关Kafka提交日志存储和复制设计的详细信息,请阅读页面。

卡夫卡流处理

只读取,写入和存储数据流是不够的,目的是启用流的实时处理。

在Kafka中,流处理器是指从输入主题获取连续数据流,对该输入执行一些处理,并产生连续数据流以输出主题的任何东西。

例如,零售应用程序可能会接受销售和发货的输入流,并输出一系列重新排序和对这些数据进行计算的价格调整。

直接使用生产者和消费者API可以做简单的处理。但是对于更复杂的转换,Kafka提供了一个完全集成的Streams API。这允许构建应用程序进行非平凡的处理,从而计算聚合关闭流或将流连接在一起。

这个工具有助于解决这类应用程序面临的难题:处理乱序数据,重新处理代码更改的输入,执行有状态的计算等等。

流API基于Kafka提供的核心原语构建:它使用生产者和消费者API进行输入,使用Kafka进行有状态存储,并在流处理器实例之间使用相同的组机制来实现容错。

放在一起

消息传递,存储和流处理的这种组合看起来很不寻常,但对于Kafka作为一个流媒体平台来说,这是非常重要的。

像HDFS这样的分布式文件系统允许存储用于批处理的静态文件。有效地,这样的系统允许存储和处理过去的历史数据。

传统的企业消息传递系统允许处理将来订阅的消息。以这种方式构建的应用程序在到达时处理将来的数据。

Kafka结合了这两种功能,并且这两种组合对于Kafka用作流式传输应用程序平台和流式传输数据管道都是至关重要的。

通过将存储和低延迟订阅相结合,流式应用程序可以同样的方式处理过去和未来的数据。这是一个单一的应用程序可以处理历史,存储的数据,而不是结束,当它达到最后一个记录,它可以继续处理未来的数据到达。这是流处理的概括概念,包括批处理以及消息驱动的应用程序。

同样,对于流式传输数据流水线,订阅实时事件的组合使得可以将Kafka用于非常低延迟的流水线; 但是可靠地存储数据的能力可以将其用于必须保证数据交付的关键数据,或者与只能定期加载数据的离线系统集成,或者可能长时间停机进行维护。流处理设施可以在数据到达时进行转换。

更多:

http://tyrion.iteye.com/blog/2408319

参考:

https://blog.csdn.net/xietingcandice/article/details/53339761

https://blog.csdn.net/qq838642798/article/details/70808557

https://blog.csdn.net/csj941227/article/details/78703641

猜你喜欢

转载自blog.csdn.net/liyanan21/article/details/81662654