1. kafka简介
Kafka作为一个集群运行在一个或多个可跨多个数据中心的服务器上,以“topics主题“的类别存储记录流,每条记录都包含一个键,一个值和一个时间戳。
Kafka 是一个分布式流媒体平台。流媒体平台有三个关键功能:
1. 发布和订阅记录流,类似于消息队列或企业消息传递系统;
2. 以容错的持久方式存储记录流;
3. 记录发生时处理流。
Kafka通常用于两大类应用:
1. 构建可在系统或应用程序之间可靠获取数据的实时流数据管道;
2. 构建转换或响应数据流的实时流应用程序。
四个核心API:
1. Producer API: 允许应用程序发布记录流至一个或多个kafka的topic。
2. Consumer API: 允许应用程序订阅一个或多个topic,并处理所产生的的数据流。
3. Streams API (流API): 允许应用程序充当流处理器,从一个或多个topics消耗输入流,并产生一个输出流至一个或多个输出的topics,有效地变换所述输入流、输出流。
4. Connector API (连接器API): 允许构建和运行kafka topics,连接到现有的应用程序或数据系统中重用生产者或消费者。例如,关系数据库的连接器可能捕获对表的每个更改。
在Kafka中,客户端和服务器之间的通信通过简单、高性能、语言无关的TCP协议完成,此协议已版本化并保持与旧版本的向后兼容性。Kafka提供Java客户端,但客户端有多种语言版本。
2. Topics 和 partitions
topics是记录流核心抽象
一个Topic可以认为是一类消息,每个topic将被分成多个partition,每个partition在存储层面是append log文件。主题是发布记录的类别或订阅源名称,Kafka的主题总是多用户的, 即一个主题可以有零个,一个或多个消费者订阅写入它的数据。
对于每个主题,Kafka集群都维护一个如下图所示的分区日志, 每个分区都是一个有序的,不可变的记录序列,不断附加到结构化的提交日志中。分区中的记录每个都分配了一个称为偏移的顺序ID号,它唯一地标识分区中的每个记录。
Kafka集群持久保存所有已发布的记录(无论是否已使用) ,使用可配置的保留期。Kafka的性能在数据大小方面实际上是恒定的,长时间存储数据不是问题。
实际上,基于每个消费者保留的唯一元数据是该消费者在日志中的偏移或位置。这种偏移由消费者控制:通常消费者在读取记录时会线性地提高其偏移量,但事实上,由于该位置由消费者控制,因此它可以按照自己喜欢的任何顺序消费记录。例如,消费者可以重置为较旧的偏移量来重新处理过去的数据,或者跳到最近的记录并从“现在”开始消费。这些功能组合意味着Kafka 消费者consumers 可以来来往往,对集群或其他消费者没有太大影响。
日志中的分区有多种用途:
1. 充当了并行性的单位。(主要)
2. 允许日志扩展到超出适合单个服务器的大小。每个单独的分区必须适合托管它的服务器,但主题可能有许多分区,因此它可以处理任意数量的数据。
Distribution分配
一个Topic的多个partitions,被分布在kafka集群中的多个server上,每个server(kafka实例)负责partitions中消息的读写操作。此外kafka还可以配置partitions需要备份的个数(replicas),每个partition将会被备份到多台机器上,以提高可用性。
基于replicated方案,需要对多个备份进行调度,每个partition都有一个server为"leader",leader负责所有的读写操作。如果leader失效,将会有其他follower来接管(成为新的leader)。但follower只是单调的和leader跟进,同步消息。而作为leader的server承载了全部的请求压力,有多少个partitions就意味着有多少个"leader",kafka会将"leader"均衡的分散在每个server上,来确保整体的性能稳定。
3. Producers&Consumers
3.1 Producers
Producers 将数据发布到指定的topics,同时Producer 也能决定将此消息归属于哪个partition,比如基于"round-robin"方式或者通过其他的一些算法等。
3.2 Consumers
3.2.1 Consumer group
每个consumer属于一个consumer group,发送到Topic的消息只会被订阅此Topic的每个group中的一个consumer消费(一个Topic的不同Partition也可以分别被一个group内多个consumer消费)。如果所有使用者实例具有相同的使用者组,则记录将有效地在使用者实例上进行负载平衡;如果所有消费者实例具有不同的消费者组,则每个记录将广播到所有消费者进程。
分析:两个服务器Kafka群集,托管四个分区(P0-P3),包含两个使用者组:消费者组A有两个消费者实例,B组有四个消费者实例。
3.2.2 Consumers kafka确保
发送到partitions中的消息将会按照它接收的顺序追加到日志中。对于消费者而言,它们消费消息的顺序和日志中消息顺序一致。
4. 为什么是Kafka?
4.1 Kafka的流概念与传统的企业邮件系统相比如何?
传统消息系统有两种模型:
1. queuing 排队
消费者池可以从服务器读取并且每个记录转到其中一个,其优势在于它允许在多个消费者实例上划分数据处理,从而实现扩展。但一旦一个进程读取它已经消失的数据,队列就不是多用户。
2. publish-subscribe发布 - 订阅
记录被广播给所有消费者,允许将数据广播到多个进程,但由于每条消息都发送给每个订阅者,因此无法进行扩展处理。
Kafaka的消费者群体概念概括了这两个概念:
1. 使用者组允许将处理划分为一组进程(使用者组的成员);
2. 允许向多个消费者组广播消息。
4.2 kafka 的优势
与传统的消息系统相比,Kafka具有更强的订购保证,其优势在于每个主题都具有以下属性:
1. 可以扩展处理并且也是多用户;
2. 不需要选择其中一个。
主题中具有并行性概念:分区 ,在消费者流程池中提供订购保证和负载平衡。每个分区仅由该组中的一个使用者使用,确保使用者是该分区的唯一读者并按顺序使用数据。由于有许多分区,这仍然可以平衡许多消费者实例的负载。
4.3 kafka作为存储系统
任何允许发布与消费消息分离的消息队列都充当了正在进行的消息的存储系统。Kafka的不同之处在于写入Kafka的数据将写入磁盘并进行复制以实现容错。Kafka允许生产者等待确认,以便在完全复制之前写入不被认为是完整的,并且即使写入的服务器失败也保证写入仍然存在。由于认真对待存储并允许客户端控制其读取位置,因此可以将Kafka视为一种专用于高性能,低延迟提交日志存储,复制和传播的专用分布式文件系统。
4.4 kafka使用场景
4.4.1 消息Messaging
Kafka可以替代传统的消息代理(将处理与数据生成器分离,缓冲未处理的消息等),且Kafka具有更好的吞吐量、内置分区、复制和容错功能,这使其成为大规模消息处理应用程序的理想解决方案。根据经验,消息传递的使用通常相对较低,但可能需要较低的端到端延迟,并且通常取决于Kafka提供的强大的耐用性保证。在这个领域,Kafka可与传统的消息传递系统(如ActiveMQ或 RabbitMQ)相媲美。
4.4.2 网站活动跟踪
Kafka的原始用例是能够将用户活动跟踪管道重建为一组实时发布 - 订阅源,这意味着站点活动(页面查看、搜索或用户可能采取的其他操作)将发布到中心主题,每个活动类型包含一个主题。这些源可用于订购一系列用例,包括实时处理,实时监控以及加载到Hadoop或离线数据仓库系统以进行脱机处理和报告。活动跟踪通常非常高,因为为每个用户页面视图生成了许多活动消息。
4.4.3 度量Metrics
Kafka通常用于运营监控数据,这涉及从分布式应用程序聚合统计信息以生成操作数据的集中式提要。
4.4.4 日志聚合
许多人使用Kafka作为日志聚合解决方案的替代品。日志聚合通常从服务器收集物理日志文件,并将它们放在中央位置(可能是文件服务器或HDFS)进行处理。Kafka抽象出文件的细节,并将日志或事件数据作为消息流更清晰地抽象出来,这允许更低延迟的处理并更容易支持多个数据源和分布式数据消耗。与Scribe或Flume等以日志为中心的系统相比,Kafka提供了同样出色的性能,由于复制而具有更强的耐用性保证,以及更低的端到端延迟。
4.4.5 流处理
许多Kafka用户在处理由多个阶段组成的管道时处理数据,其中原始输入数据从Kafka主题中消费,然后聚合,丰富或以其他方式转换为新主题以供进一步消费或后续处理。
例如,用于推荐新闻文章的处理管道可以从RSS订阅源抓取文章内容并将其发布到“文章”主题;进一步处理可能会对此内容进行规范化或重复数据删除,并将已清理的文章内容发布到新主题;最终处理阶段可能会尝试向用户推荐此内容。此类处理管道基于各个主题创建实时数据流的图形。
Kafka Streams是一个轻量级但功能强大的流处理库,在Kafka中可用于执行如上所述的此类数据处理。其他开源流处理工具包括Apache Storm和 Apache Samza。
4.4.6 Event Sourcing
Event Sourcing是一种应用程序设计风格,其中状态更改记录为按时间排序的记录序列。Kafka对非常大的存储日志数据的支持使其成为以这种风格构建的应用程序的出色后端。
4.4.7 提交日志
Kafka可以作为分布式系统的一种外部提交日志,该日志有助于在节点之间复制数据,并充当故障节点恢复其数据的重新同步机制。Kafka中的日志压缩功能有助于支持此用法,在这种用法中,Kafka类似于Apache BookKeeper项目。
8. kafka安装
8.1 下载安装
官网下载: http://kafka.apache.org/downloads.html
kafka正常运行,必须配置zookeeper。
8.2 Kafka使用简单入门
8.2.1 创建主题topics
创建一个名为“along”的主题,只包含一个分区和一个副本:
kafka-topics.sh --create
--zookeeper localhost:2181
--replication-factor 1
--partitions 1
--topic along
Created topic "along"
运行list topic命令,查看该主题:
kafka-topics.sh --list
--zookeeper localhost:2181 along
8.2.2 发送一些消息
Kafka附带一个命令行客户端,可以从文件或标准输入中获取输入,并将其作为消息发送到Kafka集群(默认情况下,每行将作为单独的消息发送)。
kafka-console-producer.sh --broker-list localhost:9092
--topic along
>This is a message
>This is another message
8.2.3 启动消费者
Kafka还有一个命令行使用者,会将消息转储到标准输出。
kafka-console-consumer.sh
--bootstrap-server localhost:9092
--topic along
--from-beginning [**]
This is a message This is another message
8.3 设置多代理Kafka群集
对于Kafka,单个代理只是一个大小为1的集群,这里将我们的集群扩展到三个节点(仍然在本地机器上)。
8.3.1 准备配置文件
cd /data/kafka_2.11-2.1.0/
cp config/server.properties config/server-1.properties
cp config/server.properties config/server-2.properties
vim config/server-1.properties
broker.id=1
listeners=PLAINTEXT://:9093
log.dirs=/tmp/kafka-logs-1
vim config/server-2.properties
broker.id=2
listeners=PLAINTEXT://:9094
log.dirs=/tmp/kafka-logs-2
broker.id 是群集中每个节点的唯一名称。必须覆盖端口和日志目录,因为我们在同一台机器上运行这些,且希望让所有代理尝试在同一端口上注册或覆盖彼此的数据。
8.3.2 开启集群另2个Kafka服务
nohup kafka-server-start.sh /data/kafka_2.11-2.1.0/config/server-1.properties &
nohup kafka-server-start.sh /data/kafka_2.11-2.1.0/config/server-2.properties &
ss -nutl Netid State
Recv-Q Send-Q Local Address:Port Peer
Address:Port
tcp LISTEN 0 50 ::ffff:127.0.0.1:9092 :::*
tcp LISTEN 0 50 ::ffff:127.0.0.1:9093 :::*
tcp LISTEN 0 50 ::ffff:127.0.0.1:9094 :::*
8.4 在集群中进行操作
1. 现在创建一个复制因子为3的新主题my-replicated-topic
kafka-topics.sh --create
--zookeeper localhost:2181
--replication-factor 3
--partitions 1
--topic my-replicated-topic
Created topic "my-replicated-topic".
2. 在一个集群中,运行“describe topics”命令查看哪个broker正在做什么
kafka-topics.sh --describe
--zookeeper localhost:2181
--topic my-replicated-topic
下面给出了所有分区的摘要,每个附加行提供有关一个分区的信息。由于我们只有一个分区用于此主题,因此只有一行。
Topic:my-replicated-topic PartitionCount:1 ReplicationFactor:3 Configs:
Topic: my-replicated-topic Partition: 0
Leader: 2 # 负责给定分区所有读取和写入的节点。节点2将成为随机选择的分区部分的领导者。
Replicas: 2,0,1 # 复制此分区日志的节点列表,无论是否为领导者
Isr: 2,0,1 # 同步”复制品的集合,副本列表的子集,该列表当前处于活跃状态且已经被领导者捕获。
3. 往新主题发布一些消息:
kafka-console-producer.sh
--broker-list localhost:9092
--topic my-replicated-topic
>my test message 1
>my test message 2
8.5 测试集群的容错性
1. 容错性测试
Broker 2 充当leader 但被kill了:
ps aux | grep server-2.properties | awk '{print $2}'
kill -9 106737
ss -nutl
tcp LISTEN 0 50 ::ffff:127.0.0.1:9092 :::*
tcp LISTEN 0 50 ::ffff:127.0.0.1:9093 :::*
2. leader 已切换到其中一个从属节点,节点2不再位于同步副本集中:
kafka-topics.sh --describe
--zookeeper localhost:2181
--topic my-replicated-topic
Topic:my-replicated-topic PartitionCount:1 ReplicationFactor:3 Configs:
Topic: my-replicated-topic Partition: 0
Leader: 0 Replicas: 2,0,1 Isr: 0,1
3. 即使最初接受写入的leader 已经失败,这些消息仍可供消费:
kafka-console-consumer.sh
--bootstrap-server localhost:9092
--from-beginning
--topic my-replicated-topic
my test message 1 my test message 2
9. 使用Kafka Connect导入/导出数据
Kafka Connect是Kafka附带的工具,用于向Kafka导入和导出数据。它是一个可扩展的工具,运行连接器,实现与外部系统交互的自定义逻辑。这些连接器将数据从文件导入Kafka主题并将数据从Kafka主题导出到文件。
1. 创建一些种子数据进行测试:
echo -e "foo\nbar" >test.txt
2. 启动两个以独立模式运行的连接器(它们在单个本地专用进程中运行),以及三个配置文件。
(1)(第一个始终是Kafka Connect流程的配置,包含常见配置,例如要连接的Kafka代理和数据的序列化格式。
(2)其余配置文件均指定要创建的连接器。这些文件包括唯一的连接器名称,要实例化的连接器类以及连接器所需的任何其他配置。
connect-standalone.sh config/connect-standalone.properties
config/connect-file-source.properties
config/connect-file-sink.properties
Kafka附带的这些示例配置文件使用你之前启动的默认本地群集配置并创建两个连接器:
1. 源连接器:从输入文件读取行并生成每个Kafka主题;
2. 宿连接器:从Kafka主题读取消息并将每个消息生成为输出文件中的一行。
3. 验证是否导入成功(另起终端)
一旦Kafka Connect进程启动,源连接器应该开始从test.txt主题读取行并将其生成到主题connect-test中,并且接收器连接器应该开始从主题读取消息connect-test 并将它们写入文件test.sink.txt。可以通过检查输出文件的内容来验证数据是否已通过整个管道传递:
cat test.sink.txt
# foo bar
注意:数据存储在Kafka主题中connect-test,因此可以运行控制台使用者来查看主题中的数据(或使用自定义使用者代码来处理它):
kafka-console-consumer.sh --bootstrap-server localhost:9092
--topic connect-test
--from-beginning {"schema":{"type":"string","optional":false},"payload":"foo"}
{"schema":{"type":"string","optional":false},"payload":"bar"}
4. 继续追加数据,验证
echo Another line>> test.txt
cat test.sink.txt foo bar Another line
kafka-console-consumer.sh --bootstrap-server localhost:9092
--topic connect-test
--from-beginning {"schema":{"type":"string", "optional":false}, "payload":"foo"}
{"schema":{"type":"string", "optional":false}, "payload":"bar"}
{"schema":{"type":"string","optional":false},"payload":"Another line"}