kafka

Kafka 是一个分布式的基于发布/订阅模式的消息队列(Message Queue),主要应用于大数据实时处理领域

特点

基础概念

消息和批次

模式

主题和分区

屏幕截图 2020-08-12 152257

生产者和消费者

屏幕截图 2020-08-12 152638

broker 和集群

屏幕截图 2020-08-12 152955

对于消息 kafka会保留一段时间或者达到一定大小的字节数 旧的消息会被删除

多集群

屏幕截图 2020-08-12 153137

使用场景

架构

屏幕截图 2020-08-03 133557

分区与副本机制

ISR:中的副本都是与 leader 同步的副本

为了描述一个副本是否与 leader 副本同步,replica.lag.time.max.ms 用来描述这个最大延迟,如果 follower 副本与 leader 副本的复制延迟超过这个时间,则认为不同步

Kafka 使用高水位(HW, Hight WaterMark)来标识分区下的哪些消息是可以被消费者消费以及进行副本间的同步

Leader epoch:可以用来确定最新的分区副本,由两部分数据组成。一个是Epoch,一个单调增加的版本号。每当副本领导权发生变更时,都会增加该版本号

zk的作用

主要为 Kafka 提供元数据的管理的功能

应用场景

搭建

配置

broker 配置

主题配置

命令操作

./kafka-topics.sh --list --zookeeper 172.17.0.1:2181
/opt/kafka/bin/kafka-topics.sh --create --zookeeper 172.17.0.1:2181 --replication-factor 1 --partitions 2 --topic my_log
./kafka-console-producer.sh --topic first --broker-list 172.17.0.1:9092
./kafka-console-consumer.sh --topic first --bootstrap-server 172.17.0.1:9092

工作流程

屏幕截图 2020-08-05 153846

Kafka 中消息是以 topic 进行分类的,生产者生产消息,消费者消费消息,都是面向 topic的

每个 partition 对应于一个 log 文件,该 log 文件中存储的就是 producer 生产的数据

Producer 生产的数据会被不断追加到该log 文件末端,在对该文件进行读写时,Kafka会充分利用PageCache来加速读写,且每条数据都有自己的 offset。消费者组中的每个消费者,都会实时记录自己消费到了哪个 offset,以便出错恢复时,从上次的位置继续消费

屏幕截图 2020-08-05 155131

index与log文件的作用:

屏幕截图 2020-08-05 155619

Kafka 对 offset的查找是基于二分查找实现的:

首先通过index文件查找offset所在的大概范围,然后再在这个范围内进行顺序查找,为了使用更少的内存空间,Kafka 采用的是稀疏不连续的索引

Kafka 利用 mmap,将更大的磁盘文件映射到了一个虚拟内存空间,也就是最近读写的数据更有可能在内存中,对于什么读写的冷数据如果进行访问,会触发缺页中断,所以 Kafka 的二分查找会优先查找热区,即最近操作的那部分数据,找到的话就不用去查冷区的数据,以此提升性能

冷区数据触发缺页中断

深入

集群成员关系

broker通过创建临时节点把自己的 ID 注册到 Zookeeper

控制器:一个特殊的broker 通过在zk创建临时节点进行选举

控制器负责在节点加入或离开集群时进行分区首领选举。控制器使用epoch 来避免“脑裂”

复制

请求处理

屏幕截图 2020-08-21 143247

生产请求:

在消息被写入分区的首领之后,broker 开始检查 acks 配置参数——如果 acks 被设为 0 或 1 ,那么 broker 立即返回响应;如果 acks 被设为 all ,那么请求会被保存在一个叫作炼狱的缓冲区里,直到首领发现所有跟随者副本都复制了消息,响应才会被返回给客户端

获取请求:

broker 将按照客户端指定的数量上限从分区里读取消息,再把消息返回给客户端。Kafka 使用零复制技术向客户端发送消息(直接从文件系统缓存复制到网卡),如果应用程序是从文件读出数据后再通过网络发送出去的场景,并且这个过程中不需要对这些数据进行处理,这种场景可以使用零拷贝

屏幕截图 2020-08-21 144218

所有同步副本复制了这些消息,才允许消费者读取它们

屏幕截图 2020-08-21 144435

物理存储

文件管理:

分区分成若干个片段 当前正在写入数据的片段叫作活跃片段

可靠数据传递

kafka 的保证:

副本的同步保证:

broker

复制系数:

主题级别 replication.factor broker级别 default.replication.factor

如果复制系数为 N,那么在 N-1 个 broker 失效的情况下,仍然能够从主题读取数据或向主题写入数据,同时 它们也会占用N倍的磁盘空间、

不完全首领选举:

如果把 unclean.leader.election.enable 设为 true ,就是允许不同步的副本成为首领 就要承担丢失数据和出现数据不一致的风险

最少同步副本:

min.insync.replicas 如果要确保已提交的数据被写入不止一个副本,就需要把最少同步副本数量设置为大一点

生产者

发送确认:

acks:0 能够通过网络把消息发送出去,那么就认为消息已成功写入

1 :意味着首领在收到消息并把它写入到分区数据文件(不一定同步到磁盘上)时 会返回确认或错误响应

all: 首领在返回确认或错误响应之前,会等待所有同步副本都收到消息

重试参数:

对于一些错误 可以通过重试来解决 如: LEADER_NOT_AVAILABLE

消费者

显示提交偏移量:

数据管道

需要考虑的问题:

Connect

启动 connect:

./bin/connect-distributed.sh ./config/connect-distributed.properties

文件数据源:

POST localhost:8083/connectors
{"name":"load-kafka-config", "config":{"connector.class":"FileStreamSource","file":"config/server.properties","topic":"kafka-config-topic"}}

传递文件数据源到主题上

深入

集群镜像

使用场景:

多集群架构

跨数据中心通信:

中心架构:

stateDiagram-v2
  direction LR
  北京Kafka集群(部分数据) --> 中心指标Kafka集群(整体数据)
  上海Kafka集群(部分数据) --> 中心指标Kafka集群(整体数据)
  广州Kafka集群(部分数据) --> 中心指标Kafka集群(整体数据)
  厦门Kafka集群(部分数据) --> 中心指标Kafka集群(整体数据)

主从架构:

stateDiagram-v2
  订单业务Kafka集群 --> 报表统计Kafka集群

双活架构:

stateDiagram-v2
  北京Kafka集群 --> 广州Kafka集群
  广州Kafka集群 --> 北京Kafka集群

主备架构:

stateDiagram-v2
  direction LR
  主Kafka集群 --> 备Kafka集群
  用户 --> 主Kafka集群: 正常情况
  用户 --> 备Kafka集群: 主集群挂掉

MirrorMaker

stateDiagram-v2
  state 源Kafka集群 {
    主题A
    主题B
    主题C
  }
  主题A --> 消费者1
  主题B --> 消费者2
  主题C --> 消费者3
  state MirrorMaker {
    消费者1 --> 生产者
    消费者2 --> 生产者
    消费者3 --> 生产者
  }
  生产者 --> 主题A0
  生产者 --> 主题B0
  生产者 --> 主题C0
  state 目标Kafka集群 {
    主题A0
    主题B0
    主题C0
  }

如果有可能,尽量让 MirrorMaker 运行在目标数据中心里

监控

所有度量指标都可以通过 Java Management Extensions(JMX)接口来访问

broker

非同步分区数量:

关键指标:

其他监控:

集群问题:

主机问题:

客户端

指标:

优化

操作系统层优化

JVM调优

Broker端调优

应用层调优

性能指标调优

流式处理

数据流:无边界数据集的抽象表示 数据流是有序的, 不可变的, 可重播的 流式处理是持续地从一个无边界的数据集读取数据,然后对它们进行处理并生成结果

概念

时间:

状态:

时间窗口:

屏幕截图 2020-08-23 112304

设计模式

单事件处理:

屏幕截图 2020-08-23 112459

本地状态事件处理:

屏幕截图 2020-08-23 112551

多阶段处理:

屏幕截图 2020-08-23 112748

外部数据源填充:

屏幕截图 2020-08-23 112929

连接流:

屏幕截图 2020-08-23 113209

对乱序事件重排序

重新处理:

使用新处理程序从头读取数据流生成结果流

Kafka Streams 架构

拓扑结构:

屏幕截图 2020-08-23 114308

对拓扑结构伸缩:

屏幕截图 2020-08-23 114438