Kafka

ZEDH

求甚解

Kafka 入门

https://aws.amazon.com/cn/msk/what-is-kafka/

https://dzone.com/articles/what-is-kafka

https://www.tutorialspoint.com/apache_kafka/apache_kafka_introduction.htm

http://kafka.apache.org/documentation/#quickstart

0.Kafka是什么

https://www.youtube.com/watch?v=aj9CDZm0Glc

Amazon

Apache Kafka 是一种分布式数据存储,经过优化以实时提取和处理流数据。流数据是指由数千个数据源持续生成的数据,通常可同时发送数据记录。流平台需要处理这些持续流入的数据,按照顺序逐步处理。

Kafka 为其用户提供三项主要功能:

  • 发布和订阅记录流
  • 按照记录的生成顺序高效地存储记录流
  • 实时处理记录流

Kafka 主要用于构建适应数据流的实时流数据管道和应用程序。它结合了消息收发、存储和流处理功能,能够存储历史和实时数据。

DZone

Kafka 是一个分布式流平台,用于发布和订阅记录流。Kafka 用于容错存储。Kafka 将主题日志分区复制到多个服务器。Kafka 旨在允许您的应用程序在记录发生时对其进行处理。Kafka 速度快,通过批处理和压缩记录有效地使用 IO。Kafka 用于解耦数据流。Kafka 用于将数据流式传输到数据湖、应用程序和实时流分析系统中。

Kafka_第1张图片

Kafka 集群保留所有已发布的记录。如果您不设置限制,它将保留记录,直到磁盘空间用完为止。您可以设置基于时间的限制(可配置的保留期)、基于大小的限制(可根据大小配置)或压缩(使用密钥保留最新版本的记录)。例如,您可以将保留策略设置为三天、两周或一个月。主题日志中的记录可供使用,直到被时间、大小或压缩丢弃。消费速度不受大小影响,因为 Kafka 总是写入主题日志的末尾。

IBM

Apache Kafka (Kafka) 是一个开源的分布式流媒体平台,支持(除其他外)开发实时、事件驱动的应用程序。那么,这意味着什么?

今天,数十亿数据源不断生成数据记录流,包括事件流。**事件是发生的动作及其发生时间的数字记录。**通常,事件是作为流程的一部分驱动另一个动作的动作。客户下订单、选择航班座位或提交注册表都是事件的示例。事件不必涉及人——例如,连接的恒温器在给定时间的温度报告也是一个事件。

这些流为实时响应数据或事件的应用程序提供了机会。流媒体平台使开发人员能够构建应用程序,以极高的速度持续使用和处理这些流,并根据它们发生的正确顺序具有高保真度和准确性。

LinkedIn 于 2011 年开发了 Kafka 作为自己使用的高吞吐量消息代理,然后将 Kafka 开源并捐赠给Apache 软件基金会 (链接位于 IBM 外部)。今天,Kafka 已经发展成为使用最广泛的流媒体平台,每天能够摄取和处理数万亿条记录,而不会随着数据量的增加而出现任何明显的性能滞后。Target、Microsoft、AirBnB 和 Netflix 等财富 500 强组织依靠 Kafka 为其客户提供实时、数据驱动的体验。

总结

  • Kafka 是一个分布式 事件流 平台
  • 它结合了消息收发、存储和流处理功能,能够存储历史和实时数据。

1. 背景

In Big Data, an enormous volume of data is used. Regarding data, we have two main challenges.The first challenge is how to collect large volume of data and the second challenge is to analyze the collected data. To overcome those challenges, you must need a messaging system.

Kafka is designed for distributed high throughput systems. Kafka tends to work very well as a replacement for a more traditional message broker. In comparison to other messaging systems, Kafka has better throughput, built-in partitioning, replication and inherent fault-tolerance, which makes it a good fit for large-scale message processing applications.

2.适用场景

  • 实时处理支付和金融交易,例如在证券交易所、银行和保险中。
  • 实时跟踪和监控汽车、卡车、车队和货物,例如物流和汽车行业。
  • 持续捕获和分析来自 IoT 设备或其他设备(例如工厂和风电场)的传感器数据。
  • 收集客户互动和订单并立即做出反应,例如在零售、酒店和旅游行业以及移动应用程序中。
  • 监测住院病人并预测病情变化,以确保在紧急情况下得到及时治疗。
  • 连接、存储和提供公司不同部门产生的数据。
  • 作为数据平台、事件驱动架构和微服务的基础。

3.特性

  • 可扩展:Kafka 的分区日志模型允许跨多个服务器分发数据,使其可扩展性超越了在单服务器上应用的情况。
  • 快速:Kafka 可解耦数据流,因此延迟非常低,速度极快。
  • 持久:分区可以跨多个服务器分发和和复制,数据全都写入到磁盘。这有助于防止服务器发生故障,使数据获得出色的容错能力和耐久性。

4.小试Kafka

Kafka的工作原理

Kafka 结合了两种消息收发模型、列队和发布-订阅,以向客户提供其各自的主要优势。通过列队可以跨多个使用器实例分发数据处理,因此具有很高的可扩展性。但是,传统队列不支持多订阅者。发布-订阅方法支持多订阅者,但是由于每条消息传送给每个订阅者,因此无法用于跨多个工作进程发布工作。Kafka uses 使用分区日志模型将这两种解决方案融合在一起。日志是一种有序的记录,这些日志分成区段或分区,分别对应不同的订阅者。这意味着,同一个主题可有多个订阅者,分别有各自的分区以获得更高的可扩展性。最后,Kafka 的模型带来可重放性,允许多个相互独立的应用程序从数据流执行读取以便按自己的速率独立地工作

队列

Kafka_第2张图片

发布-订阅

Kafka_第3张图片

快速上手

单体

http://kafka.apache.org/documentation/#quickstart

  1. 获取Kafka

    # https://www.apache.org/dyn/closer.cgi?path=/kafka/2.8.0/kafka_2.13-2.8.0.tgz
    $ wget https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/2.8.0/kafka_2.13-2.8.0.tgz
    $ tar -xzf kafka_2.13-2.8.0.tgz
    $ cd kafka_2.13-2.8.0
    
  2. 启动Kafka

    # Start the ZooKeeper service
    # Note: Soon, ZooKeeper will no longer be required by Apache Kafka.
    $ bin/zookeeper-server-start.sh config/zookeeper.properties
    # bin/windows/zookeeper-server-start.bat config/zookeeper.properties
    # 打开另一个终端会话并运行:
    # Start the Kafka broker service
    $ bin/kafka-server-start.sh config/server.properties
    # bin/windows/kafka-server-start.bat config/server.properties
    
  3. 创建一个主题来存储您的事件

    # 首先创建 topic
    $ bin/kafka-topics.sh --create --topic event01 --bootstrap-server localhost:9092
    # bin/windows/kafka-topics.bat --create --topic event01 --bootstrap-server localhost:9092
    # 带附加选项
    $ bin/kafka-topics.sh --describe --topic event01 --bootstrap-server localhost:9092
    # bin/windows/kafka-topics.bat --describe --topic event01 --bootstrap-server localhost:9092
    Topic:event01  PartitionCount:1    ReplicationFactor:1 Configs:
        Topic: event01 Partition: 0    Leader: 0   Replicas: 0 Isr: 0
    
  4. 写入事件

    Kafka 客户端通过网络与 Kafka 代理通信以写入(或读取)事件。一旦收到,代理将以持久和容错的方式存储事件,只要您需要——甚至永远。

    运行控制台生产者客户端将一些事件写入您的主题。默认情况下,您输入的每一行都会导致将单独的事件写入主题。

    # 进入后可以写入多个事件
    $ bin/kafka-console-producer.sh --topic event01 --bootstrap-server localhost:9092
    # bin/windows/kafka-console-producer.bat --topic event01 --bootstrap-server localhost:9092
    >This is my first event
    >This is my second event
    
  5. 阅读事件

    $ bin/kafka-console-consumer.sh --topic event01 --from-beginning --bootstrap-server localhost:9092
    # bin/windows/kafka-console-consumer.bat --topic event01 --from-beginning --bootstrap-server localhost:9092
    This is my first event
    This is my second event
    # ctrl + c 停止消费者客户端
    ^CProcessed a total of 2 messages
    

    因为事件持久地存储在 Kafka 中,所以它们可以被任意数量的消费者读取任意多次

集群

https://dzone.com/articles/introduction-to-apache-kafka-1

server 配置文件
-- server1.properties
broker.id=1
listeners=PLAINTEXT://:9192
log.dirs=E:\\kafka_2.13-2.8.0\\logs1

-- server2.properties
broker.id=2
listeners=PLAINTEXT://:9292
log.dirs=E:\\kafka_2.13-2.8.0\\logs2

-- server3.properties
broker.id=3
listeners=PLAINTEXT://:9392
log.dirs=E:\\kafka_2.13-2.8.0\\logs3
启动zk,server
# 启动zk
$ bin/windows/zookeeper-server-start.bat config/zookeeper.properties
# 启动各个server
$ bin/windows/kafka-server-start.bat config/server{1,2,3}.properties
# bin/windows/kafka-server-start.bat config/server1.properties
# bin/windows/kafka-server-start.bat config/server2.properties
# bin/windows/kafka-server-start.bat config/server3.properties
创建topic并查看状态
# 创建一个主体 clst
# --partitions 分区个数
# --replication-factor 复本个数,注意,不管leader或follower都是副本
# 注意 分区个数不应该大于复本个数,因为一个broker存储多个相同的分区纯粹是冗余
$ bin/windows/kafka-topics.bat --create --topic clst --zookeeper localhost:2181 --partitions 3 --replication-factor 2


# 查看 clst 的状态
$ bin/windows/kafka-topics.bat --describe --topic clst --zookeeper localhost:2181
Topic: clst     TopicId: 4jtj3tK0QDGoQojVNkqeGA PartitionCount: 3       ReplicationFactor: 2    Configs:
        Topic: clst     Partition: 0    Leader: 3       Replicas: 3,1   Isr: 3,1
        Topic: clst     Partition: 1    Leader: 1       Replicas: 1,2   Isr: 1,2
        Topic: clst     Partition: 2    Leader: 2       Replicas: 2,3   Isr: 2,3

生产者
# 启动生产者,生产者是不和zookeeper打交道的,只与kafka cluster打交道
$ bin/windows/kafka-console-producer.bat --broker-list localhost:9192 --topic clst
消费者
# 启动消费者,消费者与zk打交道,从broker拉数据
# --from-beginning 会让当前消费者不属于哪一个消费者组,效果是从头开始消费已有的数据,offset从0开始
$ bin/windows/kafka-console-consumer.bat --bootstrap-server localhost:9192 --topic clst 
$ bin/windows/kafka-console-consumer.bat --zookeeper localhost:2181 --topic clst --from-beginning
# 可能是版本问题,有些不能用,视情况看用 --bootstrap-server 还是 --zookeeker
# 按道理是从zk获取
其它常用指令
# 查看当前服务器中的所有topic
$ bin/windows/kafka-topics.bat --zookeeper localhost:2181 --list
clst


# 删除topic
# 删除操作需要在server.properties中设置 delete.topic.enable=true(此值表示物理删除)否则只是标记删除或者直接重启
# 主题删除会删除数据并且该操作是不可逆的
$ bin/windows/kafka-topics.bat --zookeeper localhost:2181 --delete --topic topicname


# 将副本重新分配给broker,让leader和follower平衡一下,使得每个broker的leader数目接近相同
$ bin/windows/kafka-preferred-replica-election.bat --zookeeper localhost:2181


# 查看消费者组
$ bin/windows/kafka-consumer-groups.bat --bootstrap-server localhost:9192,localhost:9292,localhost:9392 --list
console-consumer-35659


# 查看消费者组详情
$ bin/windows/kafka-consumer-groups.bat --bootstrap-server localhost:9192,localhost:9292,localhost:9392 --group console-consumer-35659 --describe
# 见图示
# group:消费者组
# topic:主题
# partition:分区号
# current-offset:当前索引的偏移量位置
# log-end-offset:日志结束索引偏移量,,也代表着有多少条数据
# lag:由于有延迟,因此lag表示还没有被commit的数据数量

在这里插入图片描述

语言与API

到此处,尝试使用Java和Go调用API来 生产/消费 数据

5.Kafka基础

Kafka_第4张图片

5.1 基本概念

1 zookeeper

zk 管理 kafka集群

zk 拥有集群的元数据信息,它监控集群的状态(服务注册与发现)

2 Broker

Kafka 集群包含一个或多个服务器,服务器节点称为Broker

3 Topic

注意Topic是逻辑上的概念

每条发送到Kafka集群的消息都有一个类别,这个类别就称为Topic

在实际存储的时候,并没有Topic文件,而有 Topic-partitionID

如果消费者/生产者没有指定分区,那么根据一定策略将消息保存到这个Topic下的分区

创建一个 clst 主题,然后创建 分区,分区和clst的关系:

在这里插入图片描述

物理上没有Topic,而逻辑上有Topic!!!

4 Partition & offset & segment

关于顺序

一个Topic用有 一个至多个 不同 的分区!这里强调不同,因为分区已经备份到集群的其它Broker中了,在本机备份两个分区是冗余的无用操作,创建时会直接报错

每个Partition都有Leader,只能从Leader对分区进行操作,这里Follower只是起到备份的作用

分区内的数据是有序的,但是不同的分区之间是无序的!因此消费时不能保证数据的顺序,如果需要严格保证消息消费的顺序,则将分区数量设置为1即可

当生产者产生数据的时候,根据分配策略,选择分区,然后将消息追加到指定的分区的末尾(队列)

  • partition数据路由规则
    1. 指定了partition,则直接使用
    2. 未指定partition,但指定key,通过对key的value进行hash选出一个partition
    3. partition和key都未指定,使用轮询选出一个partition

每条消息都有一个自增的编号offset:

  • 标识顺序
  • 标识消息的偏移量
关于存储和分区中的文件

每个分区文件夹中都有但不限于这些文件

名称/类型 意义 备注
*.log 存储消息实体的文件 单个log文件最大上限为1G,一个分区可以有多个log文件,文件名即为索引的偏移量
*.index 记录消息的offset以及消息在log文件中的位置的索引 稀疏存储(并不是每一条数据都会建立索引,考虑到index文件在加载到内存的时候,能不占用大量的内存和CPU资源)
*.timeindex 记录消息的timestamp和offset的索引 稀疏存储
log/index文件名:00000000000000000000 此文件第一条消息的偏移量

Kafka_第5张图片

.log文件的消息结构可以如下表示:

Kafka_第6张图片

各字段说明:

  • CRC32:CRC是循环冗余校验,CRC32,32表示多项式最高阶为32;
  • magic:魔数,kafka服务程序协议版本号;
  • attribute:低两位表示压缩方式,第三位表示时间戳类型,高4bit保留;
  • timestamp:创建消息的时间戳,当magic>0时必须包含此字段;
  • key-length:key的长度;
  • key:消息的key;
  • payload-length:消息体实际数据长度;
  • payload:消息体实际数据,在kafka中消息的内容称为payload!而不是data或者message。

index 文件中 一项数据由 offset和position 组成,需要获取数据时,首先查找offset,如果索引命中,则直接根据对应的position从log文件中找;如果未命中(因为稀疏存储offset),则找到小于这个offset的最大索引值和此索引的下一个索引,然后利用二分查找找到log文件中的条目

采用稀疏存储,避免索引文件占用过多的空间和资源,减轻内存的压力

从文件索引的方式可以看出kafka在速度方面的优势,我们知道kafka用java实现,java对IO操作提供了NIO(多路复用),使用seek()在log文件转到offset对应的position,然后就可以读取数据了。顺序读取速度比随机读取速度要快很多,甚至机械硬盘的顺序读取速度比固态硬盘的随机读取速度还要快,并且通过 批量 存/取 数据,提高了吞吐量。

kafka 通过以下 5 个层面,实现了时间复杂度为 O(1) 的读取速度:

topic 分类 -> 消息分区(partition) -> 数据分块(segment) -> 间隙索引(稀疏存储 索引) -> 顺序读写

segment

为了方便管理kafka 副本中的数据,将一个副本拆分成多个大小相等的数据段,称为segment。注意,这里指的是大小相等,而不等同于消息数量相等。

segment = *.log+ *.index + *.timestamp

可能还会有 *.snapshot(记录了生产者的事务信息),*.swap(用于恢复segment),*.txnindex(记录了中断的事务信息)

其实就是上面说的,单个log文件大小上限默认为1GB,超过就创建新的segment

# ---------------------------------- server.properties ----------------------------------
# The maximum size of a log segment file. When this size is reached a new log segment will be created.
# 1GB
log.segment.bytes=1073741824

5 Leader & Follower

在kafka集群中,如果一开始设置的 --replication-factor 的值为n,并且n大于1,那么在集群中,就会有n个broker有这个分区的副本,只有分区是Leader,才能提供读写,而Follower只是起到了备份的作用(ISR后面会讲)

在第4章的集群示例中,我们给Topic clst 创建了 3个分区,每个分区创建2个副本,查看 clst 的状态,可以看到分区的Leader和Follower情况

$ bin/windows/kafka-topics.bat --create --topic clst --zookeeper localhost:2181 --partitions 3 --replication-factor 2
# 查看 clst 的状态
$ bin/windows/kafka-topics.bat --describe --topic clst --zookeeper localhost:2181
Topic: clst     TopicId: 4jtj3tK0QDGoQojVNkqeGA PartitionCount: 3       ReplicationFactor: 2    Configs:
        Topic: clst     Partition: 0    Leader: 3       Replicas: 3,1   Isr: 3,1
        Topic: clst     Partition: 1    Leader: 1       Replicas: 1,2   Isr: 1,2
        Topic: clst     Partition: 2    Leader: 2       Replicas: 2,3   Isr: 2,3

6 replication

replication指的就是分区的副本

7 producer

生产者,将消息 push 到集群

前面说到,生产和消费数据都是跟Leader分区打交道,但是生产者怎么知道集群中的Leader分区是哪个?Kafka是这样做的:让消费者知道集群的元数据信息,集群的每一个Broker都有跟zookeeper周期性交互,将集群的元数据保存在本地,然后消费者可以通过任意一个Broker获取整个集群的元数据,然后根据消费者的策略,将数据push到指定的 Broker-Topic-Partition 中。

策略一般有 轮询、随机、基于某个key的散列,还能自定义策略。这些策略由生产者自行实现。这个我在Java编写的低代码测试中有做,可以自行查阅。

Kafka_第7张图片

更深层次的内容在以后再整理,这里仅做初步的认识。

8 consumer & consumer group

消费者/消费者组,从集群 pull 消息

consumer和consumer group虽然说都是消费数据,但是其消费的细节不一样。

consumer group消费数据时,仅有一个consumer成员可以从一个topic-partition消费数据,而别的成员不能读取该topic-partition中pull数据,但是可以pull其它的topic-partition。

除了通过offset索引,还能通过时间戳索引,时间戳索引文件与log文件同名,后缀为 *.timestamp

producer 不在 zk中注册,consumer 在zk 中注册。

kafka提供了两套consumer API,高级、低级 API。高级API

9 ISR

ACK是确认信号(acknowledge,类似计网)。acks是生产者的配置参数

三种值(String):

  • acks=0,生产者不等待来自代理的ack,不保证代理已收到消息
  • acks=1,生产者只会等待Leader的ack,Leader会将消息保存到log中才会返回ack
  • acks=all,当所有同步副本都收到并记录到log中时,生产者才会得到ack。Leader将等待完整的同步副本集来确认记录。这往往耗时更久,但是提供了最强的消息持久性

ISR,即 In-Sync Replica,在同步状态的副本,同步副本

What does In-Sync Replica in Apache Kafka Really Mean

TODO

6.同类技术选型

RabbitMQ 是一种开源消息代理,使用消息收发队列方法。队列在节点集群中传播,还可以复制,每条消息都只能传送到单个使用器。

特性 APACHE KAFKA RABBITMQ
架构 Kafka 使用分区日志模型,结合了消息收发队列和发送-订阅方法。 RabbitMQ 使用消息收发队列。
可扩展性 Kafka 允许跨不同服务器分发分区,因此具有可扩展性。 增加队列中的使用器数量可以将处理扩展到竞争使用器。
消息保留 基于策略,例如消息可以存储一天。用户可以配置此保留窗口。 基于确认,表示消息在使用后被删除。
多使用器 多个使用器可以订阅相同主题,因为 Kafka 允许将同一条消息重放指定的时间长度。 多个使用器无法全部接收同一条消息,因为消息在使用后将被删除。
复制 自动复制主题,但是用户可以手动将主题配置为不复制。 消息不会自动复制,但是用户可以手动将其配置为复制。
消息排序 由于采用了分区日志架构,每个使用器按顺序收到信息。 消息按照其到达队列的顺序传送给使用器。如果有竞争使用器,每个使用器都将处理该消息的子集。
协议 Kafka 通过 TCP 使用二进制协议。 高级消息收发队列协议 (AMQP) 及通过插件获得的支持:MQTT、STOMP。

Kafka 深入

这一单元将涉及到更深层次的Kafka的知识,包括存储、生产者、消费者等,具体到kafka是如何做的,如何实现的

TODO

Java vs. Kakfa

代码放在gitee仓库 https://gitee.com/zedh/java-kafka-demo

Go vs. Kafka

代码放在gitee仓库 https://gitee.com/zedh/go-kafka-demo

参考

Kafka中的索引机制

Kafka 工作流程及文件存储机制

Kafka(二)消息的生产

Deep Dive Into Apache Kafka | Storage Internals

大数据开发:Kafka日志结构

What does In-Sync Replica in Apache Kafka Really Mean

你可能感兴趣的:(kafka,分布式)