【1】初识Kafka

[TOC]

前言

经历了一小段动荡的日子,总算找到了当下的路。有些日子没有真的去学习些新的知识了,大多数时间里都在熟悉新的业务,几番挣扎。是时候该给自己找点事做了。而至于为什么选择 Kafka,一方面的确是想折腾折腾自己,别太舒服了。另一方面是新的工作上有在使用,但仅仅会使用是远远不够的,我实在是很想知道为什么使用,以及有没有更好的选择,这些问题希望能在2020年的春节来临之前有个答案。

1. 初识Kafka

关于Kafka是什么,先看搜索引擎得到的答案:

Apache Kafka is a Distributed Streaming Platform

翻译之就是它是一个分布式流处理平台,而作为一个流处理平台它提供了如下关键能力

    1. 提供发布/订阅流的能力,基于这个能力它可以作为消息中间件使用,类似RocketMQ等,一般都是用来做系统的削峰填谷和系统解耦
    1. 提供实时的流数据管道,可靠地获取系统和应用程序之间的数据,并在大数据中作为各个系统间的粘合剂

2. Kafka体系结构

2.1 核心API

Kafka 有4个模块的核心API,分别是:

  1. Producer API: 通过 Producer API可以发送消息到一个或多个Topic
  2. Consumer API: 通过 Consumer API订阅一个或多个Topic, 并且负责处理消息
  3. Streams API: 通过 Streams API充当一个流处理器,从1个或多个topic消费输入流,并生产一个输出流到1个或多个输出topic,有效地将输入流转换到输出流。
  4. Connector API: 通过API允许构建或运行可重复使用的生产者或消费者,将topic连接到现有的应用程序或数据系统。
2.2 核心角色

kafka 有几个核心角色

  1. Topic: Kafka 可以提供发布/订阅的解决方案, 而发布订阅一般都是有一个主题的,在Kafka中都是基于Topic的,一般每个业务或者应用都会有自己的主题Topic,这个和目前的RocketMQ这些类似。
  2. Producer: 向某个主题发送消息的客户端就是生产者 Producer,生产者会不断向多个 Topic 发送消息。
  3. Consumer: 来自Producer发送的消息都是需要被其它业务方去接收处理的,这些业务方订阅这些消息,也就是消费者 Consumer。
  4. Broker: 已发布的消息保存在一组服务器中,称之为Kafka集群。集群中的每一个服务器都是一个代理(Broker). 消费者可以订阅一个或多个主题(topic),并从Broker拉数据,从而消费这些已发布的消息。
2.3 基本原理

通常来说,消息系统的工作流程总体上是类似的,生产者产生消息事件发送到中间的服务器上,消费者从中间的服务器接收这些消息并进行消费。同时又为了适用不同的业务提供了队列模式和发布订阅模式。此外中间的服务器为了确保消息不丢失等问题还会做些额外的处理,比如持久化,分区,主备等等。

2.3.1 消息的存储与Topic分区

Kafka中的每条消息都称为一个 record, 它是由一个key,一个 value 和时间戳构成。Kafka 使用消息日志的方式保存消息,一个日志就对应着磁盘上的一个只能追加内容的物理文件。数据持久化伴随着磁盘IO的操作,只能追加的话就代表着IO是顺序的,不会是随机的,随机IO其实是比较耗时的,这方面可以提高系统的整体性能。 (ps: 参照 为什么随机IO比顺序IO要慢很多)

生产者向Broker的某个Topic下发送消息,如果消息很多,也会出现把一台Broker上磁盘空间被打满的情况, 所以就需要一种水平扩展机制,类似redis的分片那种,将数据分布在不同的机器上,在kafka中是按照topic进行分区的,每一个分区都是一个顺序的、不可变的消息队列, 并且可以持续的添加。分区中的消息都被分了一个序列号,称之为偏移量(offset),空的分区offser从0开始,第一条消息的偏移量为0,然后递增。在每个分区中此偏移量都是唯一的,显然分区的方式实现了kafka的负载均衡策略。Kafka集群保存了所有的消息,直到它们过期,无论消息是否被消费。实际上消费者消费消息的时候也是通过自身持有的消息消费偏移量才知道目前消费的进度。

Kafka中采用分区的设计有几个目的:

  1. 可以处理更多的消息,不受单台服务器的限制, Topic拥有多个分区意味着它可以不受限的处理更多的数据。
  2. 分区可以作为并行处理的单元,如下展示了一台Broker内的不同topic的生产消费情况

红色的标号代表leader


【1】初识Kafka_第1张图片
image.png
【1】初识Kafka_第2张图片
image.png
2.3.2 副本机制

Kafka集群是由多个 Broker 组成的,它们一般会运行在不同的机器上,为Kafka提供高可用方案。此外实现高可用,只是解决单点问题还是不够的,它还提供了数据备份机制,也就是提供一份冗余数据,也即是我们所说的 Leader 和 Follower。在Kafka中 Follower 只是备份 Leader的数据,不和外界交互, Leader 会将自己处理的数据同步给 Follower。副本的工作机制也很简单:生产者总是向Leader写消息,而消费者总是从Leader读消息。至于Follower,它只做一件事:向Leader发送请求,请求Leader把最新生产的消息发给它,这样它能保持与Leader的数据同步,如果leader宕机,其它的一个follower会被推举为新的leader。此外需要注意的是,它是针对分区的副本机制,并不是整个Broker,这也是它实现了内部的负载均衡的策略之一。

2.3.3 生产者

生产者往某个Topic上发布消息。生产者也负责选择发布到Topic上的哪一个分区。最简单的方式从分区列表中轮流选择。也可以根据某种算法依照权重选择分区,开发者负责如何选择分区的算法。

2.3.4 消费者

kafka中消费者组有两个概念:

  • 队列:消费者组(consumer group)允许同名的消费者组成员瓜分处理。
  • 发布订阅:允许你广播消息给多个消费者组(不同名)。

队列处理模式中,一组消费者从服务器读取消息,一条消息只有其中的一个消费者来处理,也就是同一个消费者组只会有一个消费者去消费消息。当有很多的队列模式的话,也是可以实现发布/订阅模型的。
此外 kafka 有比传统的消息系统更强的顺序保证。传统的消息系统按顺序保存数据,如果多个消费者从队列消费,则服务器按存储的顺序发送消息,但是,尽管服务器按顺序发送,消息异步传递到消费者,因此消息可能乱序到达消费者。这意味着消息存在并行消费的情况,顺序就无法保证。消息系统常常通过仅设1个消费者来解决这个问题,但是这意味着没用到并行处理。
kafka做的更好。通过并行topic分区 —— kafka提供了顺序保证和负载均衡。每个分区仅由同一个消费者组中的一个消费者消费到。并确保消费者是该分区的唯一消费者,并按顺序消费数据。每个topic有多个分区,则需要对多个消费者做负载均衡,但请注意,相同的消费者组中不能有比分区更多的消费者,否则多出的消费者一直处于空等待,不会收到消息。

2.3.5 kafka的流处理

上面一直在说kafka是如何进行读写的,但是实际上kafka最大的魅力在于它的实时流式处理,这也是为什么现在众多的大数据系统都需要Kafka进行支持的原因。在kafka中,流处理持续的从topic中获取输入的数据,然后进行加工处理再输出,比如调整价格,进行数据统计等,对于复杂的转换,Kafka提供了更强大的Streams API。可构建聚合计算或连接流到一起的复杂应用程序。这部分描述起来很简单,实际原理上还是有些复杂的,这里先简单知道它的作用。

2.4 kafka应用场景

这部分简单列的几个公司里常见的使用场景,实际上Kafka的能力远不止这些,它能做的事情还有很多。

2.4.1 消息

kafka更好的替换传统的消息系统,消息系统被用于各种场景(系统解耦、削峰填谷),与大多数消息系统比较,kafka有更好的吞吐量,内置分区,副本和故障转移,这有利于处理大规模的消息。

2.4.2 日志聚合

许多人使用Kafka作为日志聚合解决方案的替代品。日志聚合通常从服务器中收集物理日志文件,并将它们放在中央位置(可能是文件服务器或HDFS)进行处理。Kafka抽象出文件的细节,并将日志或事件数据更清晰地抽象为消息流。这允许更低延迟的处理并更容易支持多个数据源和分布式数据消费。

2.4.3 流处理

kKafka Stream是构建流处理应用,尤其是转变Kafka输入Topic为Kafka输出Topic(或调用外部服务,更新数据库)应用的库。让你能够以分布式、容错和简洁的代码做到这一点。
相比其它的流处理平台,它的流处理特点有:

  • 具有毫秒级延迟的Event-at-a-time处理(不是小批量)
  • 状态处理,包括分布式Join和聚合
  • 方便的DSL
  • 使用DataFlow-like模型处理带有window的无序数据
  • 分布式处理和快速故障切换容错
  • 再处理能力,以便当你代码改动时,重新计算输出
  • 无停机时间滚动部署

总结

本文首先了解了Kafka是干嘛的--它可以作为分布式流处理平台,基于它的一些特性,它还能够作为消息中间件去使用。接着了解了它的体系结构,包括副本、分区、流处理、生产者、消费者的简单处理流程概括。最后列举了几个生产环境上的使用场景,比如消息中间件、分布式海量日志聚合、流处理平台等等。

插入的问题

在Mysql中,主备一般都是同时面向客户端的,而在Kafka的分区的副本机制并不提供读,原因是什么?
首先要知道Mysql为什么会提供备读,主要是为了实现负载均衡和提高吞吐量,此外主从复制只是正向的过程,读就读了,主不需要知道记录读取了多少次。而kafka不同,如下:

  1. kafka已经在Broker上的Topic中分区了,已经实现了负载均衡。
  2. kafka保存的数据和数据库中的数据有着实质性的区别,kafka中保存的数据是需要被消费的,它是流数据,并且消费需要位移,而数据库就是存储到一页一页上的,如果可以从 follower上读的话,那么主备之间的消费位移offset的控制将会带来更不必要的复杂性。如果 follower 出问题了也不是很好处理。

你可能感兴趣的:(【1】初识Kafka)