
@H_
502_5@kafka对于构建实时的数据管道和流应用是很有用的。
@H_
502_5@Apache Kafka是一个分布式的流平台。这是什么意思呢?
@H_
502_5@我们考虑流平台有三个关键的能力:
- 它可以发布订阅流。这一点和消息队列或者企业消息系统很类似。
- 它可以存储流,并且可以容错。
- 它可以处理流
@H_
502_5@Kafa有什么用呢?
@H_
502_5@它被用于两类应用:
- 在系统和应用之间构建实时的流管道
- 构建实时的流应用
@H_
502_5@那么Kafka是怎样做到这些事情的呢?
@H_
502_5@首先来看一些概念:
- Kafka是以集群方式运行的
- Kafka集群将流记录存储在被叫做topics的分类中
- 每一条记录由一个key,一个value和一个timestamp组成
@H_
502_5@Kafka有四个核心的API:
-
Producer API允许一个应用发布一条流记录到一个或者多个topics中
-
Consumer API允许一个应用订阅一个或多个topics,并且处理记录流
-
Streams API允许一个应用充当流处理器的角色,从一个或多个topics那里消费一个输入流并且生产一个输出流到一个或多个topics,有效的将输入流转换为输出流
-
Connector API允许构建并运行可重用的可以将Kafka连接到已存在的应用或者数据系统上的producer或者consumer。例如,连接关系型数据库。
@H_
502_5@在Kafka中,客户端和服务器端的通信被做成是简单的、高
性能的、基于TCP协议的。
@H_
502_5@

@H_
502_5@
Topics and Logs
@H_
502_5@让我们首先深入到核心抽象,Kafka提供
a stream of records —— the topic
@H_
502_5@一个topic是一个
分类,记录是被发布到这里面的。在Kafka中,topics总是有多个
订阅者的;因此,一个topic可以有多个0个,1个,或者多个消费者来
订阅的。
@H_
502_5@每个topic,Kafka集群维护一个partitioned log(分区日志),它们看起来是这个样子的:
@H_
502_5@

@H_
502_5@每个分区都是一个有序的、不可变的序列,这些序列都是结构化的提交日志。分区中的每个记录都被指定了一个序列id编号,被称之为offset,而且它是分区中每条记录的唯一标识。
@H_
502_5@Kafka集群操持所有的发布记录,无论这些记录是否已经被消费,这一点是可以配置的。例如,如果这个保留策略设置的是2天,那么一个记录被发布过了2天以后它仍然可以被消费,但是为了腾出空间来,它可能会被丢弃。Kaka的
性能是高效的稳定的,所有存储数据很长时间不是一个问题。
@H_
502_5@

@H_
502_5@事实上,元数据是保存在每个消费者那里的,最基本的是offset或者叫position,它们都是以消费者日志形式保存的。offset是由消费者来控制的:通常一个消费者会增长它的偏移量,事实上,自从消费者可以控制位置它可以以任意顺序消费记录。例如,一个消费者可以重置到一个旧的offset以处理之前的记录。
@H_
502_5@这个特性就意味着,kafka的消费者是非常廉价的 —— 它们可以来去自如而不受集群和其它消费者的影响。
@H_
502_5@日志分区有几个目的。第一,允许日志是伸缩的,大小可以超过单个服务器,每一个独立的分区必须安装在它所在主机的那个服务器上,但是一个topic可以有多个分区,所有它可以处理任意
数量的数据。第二,作为一个并行单元。
Distribution
@H_
502_5@日志分区是被分布在集群中的服务器上的,每个服务器处理数据和请求都共享这些分区。为了容错,每个分区会交叉复制,副本的数据是可以配置的。
@H_
502_5@每个分区中有一个服务器充当“leader”,有0个或者多个服务器充当“followers”。leader处理所有的读和写请求,而follower被动的从leader那里复制。如果leader失败了,其中一个follower将
自动成为新的leader。每个充当leader的服务器可能是一些分区的leader,同时又是另一些分区的follower,所以在集群中
负载是平衡的。
Producers
@H_
502_5@
生成者发布数据到topics。生产者负责选择哪个记录指定到哪个分区。可以以一个轮询的方式简单的来实现
负载均衡。
Consumers
@H_
502_5@消费者用一个“
consumer group name”来
标记它们自己,topic中的每个记录被投递到一个
订阅者消费组中的一个消费者实例。每个消费者实例分开处理。
@H_
502_5@如果所有的消费者实例都在相同的消费者组中,那么记录有效的在消费者之间
负载均衡。
@H_
502_5@如果所有的消费者实例在不同的消费者组中,那么每一条记录都会被广播给所有的消费者。
@H_
502_5@

@H_
502_5@如图,一个Kafka集群有2个服务器,4个分区(P0—P3),2个消费者分组。消费者分组A有2个消费者实例,组B有4个。
@H_
502_5@通常,我们会发现,topic有许多消费者分组,每个组都是一个"logical subscriber"(逻辑
订阅者)。每个组由许多消费者实例组成,实例是可伸缩的可容错的。
@H_
502_5@Kafka只提供分区中的记录的总的顺序,而不保证分区之间的顺序。
Guarantees
@H_
502_5@一个高级别的kafka给出下列保证:
- 生产者发送到topic分区的消息是按照它们被发送的顺序追加的。因此,如果记录M1和M2都是被同一个生产者发送的,并且M1在前M2在后,那么M1在分区中的偏移量将比M2小,而且M1的日志也在M2的前面。
- 一个消费者实例看到记录的顺序是按照记录存储在日志中的顺序的
- 假设topic的副本因子是N,那么我们可以容忍N-1个服务失败,也不会丢失任何的提交日志
Kafka as a Messaging System
@H_
502_5@消息传统上有两种模型:queuing 和 publish-subscribe(点对点队列模型和发布
订阅模型)。在队列模型中,每个消息只能被消费一次;在发布
订阅模型中,消息可以广播给所有的消费者。这两种模型各有利弊。
@H_
502_5@Kafka中的消费者分组的概念就是在从这两种模型中衍生出来的。和队列模型一些,消费者分组允许你在处理集合之上分开处理。和发布
订阅模型一样,kafka允许你广播消息给多个消费者分组。
@H_
502_5@Kafka的模型的优势在于它的每个topic有这样一些
属性:它可以伸缩处理,而且它有多个
订阅者
@H_
502_5@相对于传统的消息系统而言,Kakfa有更强的顺序保证。
@H_
502_5@传统的队列在服务器上按顺序保存记录,而且多个消费者从队列中消费记录是按照记录被存储的顺序来消费的。虽然服务器是按顺序处理记录的,但是记录是异步投递给消费者的,所以它们可能以不同的顺序到达消费者。也就是说,在并行消费的时候会丢失一定百分比的顺序。消息系统中一个概念叫"exclusive consumer"它允许只能有一个消费者来处理,也就意味着是串行处理。
@H_
502_5@Kafka做得更好。它有一个概念叫“parallelism—the partition—within the topics”(在topics的分区下的并行)。kafka既保证顺序同时还提供
负载均衡。这一切都归功于给消费者分组中的消费者指定topic的分区,以至于每个分区都可以被一个消费者精确的消费。注意分组中的消费者
数量不能比分区数还多。
Kafka as a Storage System
@H_
502_5@任何消息队列都允许发布消息和消费消息解耦,在这个过程中扮演一个存储系统的角色。写到kafka的数据被写到磁盘并且被复制。kafka允许生产者等待确认,以至于只有当数据被完全复制并且保证已经被持久化了才能认为这个写操作是完成的。
@H_
502_5@不管你是持久化50KB还是50TB的数据,kakfa执行的操作都是一样的。
@H_
502_5@你可以把kafka当做一种特别的分布式
文件系统,它高
性能、低延迟的提交日志存储、副本。
Kafka for Stream Processing
@H_
502_5@仅仅只是读写存储流数据是不够的,要能够实时处理流。
@H_
502_5@kafka的流处理器是从输入topic那里持续不断的接收流,然后对这些输入做一些处理,并且
生成持续不断的流数据到
输出topic。
@H_
502_5@例如,一个零售应用可能采集销售和物流的的数据作为输入流,然后基于这些数据进行计算,从而
生成再次订购和价格调整的
输出流。
@H_
502_5@
@H_
502_5@参考 http://kafka.apache.org/intro
@H_
502_5@
本节重点
@H_
502_5@1、kafka是一个分布式的流平台
@H_
502_5@2、kafka有什么用?
@H_
502_5@3、基本概念
- kafka是以集群方式运行的,集群可以是一台或者多台服务器
- 记录按照类别来存储,这些类别叫topics。可以简单的理解为,数据存储在topics中
- 每条记录由key、value、timestamp组成
@H_
502_5@4、核心API
- Producer:生产者,发布记录(消息)到一个或多个topics中
- Consumer:消费者,订阅一个或者多个topics
- Streams:流处理器,从一个或多个topics那里消费输入流并且生成输出流到一个或多个topics
- Connector:构建可以连接到外部的应用或者数据系统的可重用的生产者或消费者
@H_
502_5@5、
主题和日志
@H_
502_5@ 5.1、一个
主题就是一个
分类,记录被发布到某个
主题中,
主题总是有多个
订阅者,一个
主题可以有0个或1个或多个消费者
@H_
502_5@ 5.2、每个
主题都有一个分区日志。每个分区都是一个有序的、不可变的记录序列,记录被持续不断的追加到分区中
@H_
502_5@ 5.3、记录是一个结构化的提交日志(a structured commit log)
@H_
502_5@ 5.4、分区中的每条记录都被指定了一个唯一的id号,叫做offset。offset是由消费者控制的。
@H_
502_5@ 5.5、kafka保存所有已发布的记录,不管它们是不是已经被消费。保留的周期是可配置的。
@H_
502_5@ 5.6、为什么要分区呢?分区可以突破单台服务器的限制。
@H_
502_5@6、分布
@H_
502_5@ 6.1、日志分区被分布在集群中的服务器之上,这些分区之下的每个服务器处理数据和请求的时候共享此分区,每个分区会被复制到其它服务器上,副本的
数量可配置。
@H_
502_5@ 6.2、每个分区中,有一个服务器充当"leader"的角色,有0个或者多个充当"follower"的角色。leader负责处理所有读写请求,而follower被动的从leader那里复制。如果leader死了,其中一个follower会
自动成为leader。一个服务器可能是它所在的那些分区的其中一个分区的leader的同时也可能是其它分区的follower。(PS:这段话的意思是,一个分区可能有1台或者多台服务器组成,在组成个分区的服务器中有一个服务器是leader角色,其余是follower角色,leader角色负责这个分区的所有读写操作,而follower则被动的从leader那里复制数据。而且,一个服务器可能在这个分区的leader,但同时也可能是别的分区的follower。)
@H_
502_5@7、生产者
@H_
502_5@ 生产者负责指定记录发布到哪个topic的哪个分区中
@H_
502_5@8、消费者
@H_
502_5@ 8.1、消费者用消费者组名来
标记它们自己,每个消费者分组都是topics的一个逻辑
订阅者
@H_
502_5@ 8.2、被发布到topics中的每一条记录会被投递到每个
订阅的消费者分组中的一个消费实例
@H_
502_5@ 8.3、每个消费者分组由多个消费者实例组成,而且实例的
数量是可伸缩的
@H_
502_5@9、保证
- 同一个消费者发送的同一个topic同一个分区中的消息会按照它们发送的顺序依次追加。假设M1和M2都是由同一个分区发送的消息,而且M1先被发送,那么M1的offset必定比M2小
- 消费者是按照消息存储的顺序看到消息的
- 假设副本因子是N,那么即使有N-1个服务器挂了也不会丢失任何记录
@H_
502_5@10、kafka作为消息系统
@H_
502_5@ 10.1、topics中的每条记录只会被投递到每个
订阅的消费者分组中的一个消费者实例。也就是说,假设有2个消费者分组都
订阅了这个topics,并且每个分组都有3个消费者实例,那么这个topics中的每条记录只会投递2份分别给这两个分组,每个分组收到这条记录以后只能由该分组中的一个消费者实例消费。
@H_
502_5@ 10.2、基于第一点,那么,如果
订阅这个topics的所有消费者都属于同一个分组,那么这就相当于点对点队列模型;如果
订阅的所有消费者都属于不同的消费者分组,那么这就相当于是发布
订阅模型。
@H_
502_5@ 10.3、kafka保证同一个生产者发送到同一个topics下的同一个分区的消息的存储顺序和它们发送的顺序一致,而且消费这个分区的消费者看到消息的顺序和它们存储的顺序是一样的。
@H_
502_5@ 10.4、
主题下分区中并行,kafka既保证顺序又能够
负载均衡。这一切都归功于指定分区到分组中的消费者,以至于每个分区只能被消费者分组中的一个消费者消费。通过这样做,就可以确保消费者只能按顺序消费数据。
@H_
502_5@11、两张很重要的图
@H_
502_5@


@H_
502_5@