从 Kafka 到 Pulsar:数据流演进之路 | 青训营笔记

80 阅读11分钟

这是我参与「第四届青训营 」笔记创作活动的第11天

Lecture12. 从 Kafka 到 Pulsar:数据流演进之路

01. 消息队列概述

1.1.消息队列的应用场景

  • MQ消息通道
  • EventBridge 事件总线
  • Data Platform流数据平台

1.1.1. MQ消息通道

  • 异步解耦
  • 削峰填谷
  • 高可用
  • 发布订阅

1.1.2 EventBridge数据总线

  • 事件源:将云服务、自定义应用、SaaS应用等应用程序产生的事件消息发布到事件集。
  • 事件集:存储接收到的事件消息,并根据事件规则将事件消息路由到事件目标。
  • 事件目标:消费事件消息。

1.1.3 Data Platform流数据平台

  1. 提供批/流数据处理能力
  2. 各类组件提供各类Connect
  3. 提供 Streaming/Function能力
  4. 根据数据schema灵活的进行数据预处理

1.2 主流消息队列的相关介绍

hadoop生态

02. Kafka详解

2.1 Kafka架构介绍

2.1.1 Zookeeper

Kafka存储数据:

  1. Broker Meta信息(I临时节点)
  2. Controller信息(l临时节点)
  3. Topic信息(持久节点)
  4. Confiq信息(持久节点)

选举机制:Paxos机制

  • Leaeder和Follower会投票

提供—致性:

  • 写入(强一致性)
  • 读取(会话一致性)

提供可用性:

  • 一半以上节点存活即可读写

提供功能:

  • watch机制
  • 持久/临时节点能力

2.1.2 Broker

为了宕机容灾

Broker角色

  • 若干个 Broker 节点组成 Kafka集群
  • Broker 作为消息的接收模块,使用 React网络模型进行消息数据的接收.
  • Broker作为消息的持久化模块,进行消息的副本复制以及持久化
  • Broker作为高可用模块,通过副本间的Failover进行高可用保证

2.1.3.2 Controller (比较特殊的Broker)选举

  • Broker启动会尝试去水中注册controller节点
  • 注册上controller节点的broker即为controller
  • 其余 broker 会 watch controller节点,节点出现异常则进行重新注册

Controller 作用

  • Broker 重启/宕机时,负责副本的Failover切换
  • Topic创建/删除时,负责Topic meta信息广播
  • 集群扩缩容时,进行状态控制
  • Partition/Replica状态机维护

2.1.4 Coordinator

特殊的Broker,消费端的控制

  • 负责topic-partition<->consumer的负载均衡

  • 根据不同的场景提供不同的分配策略

    • Dynamic Membership Protocol
    • Static Membership Protocol
    • Incremental Cooperative Rebalance

2.2 Kafka高可用

Kafka高可用

高可用定义:

  • 高可用最常见:多副本

  • 副本同步机制

    • 提供lsr副本复制机制,提供热备功能
    • 写入端提供ack=0,-1,1机制,控制副本同步强弱
  • 副本切换机制

    • 提供clean / unclean副本选举机制

2.2.1 Kafka副本ISR 机制

AR

  • Assign Replica,已经分配的所有副本

OSR

  • Out Sync Replica,很久没有同步数据的副本

ISR

  • 一直都在同步数据的副本
  • 可以作为热备进行切换的副本
  • min.insync.replicas最少isr数量配置

2.2.2 Kafka写入Ack机制

  • Ack = 1

    • Leader 副本写入成功,Producer 即认为写成功
  • Ack = 0

    • OneWay 模式
    • Producer 发送后即为成功
  • Ack = -1

    • ISR中所有副本都成功,Producer 才认为写成功

2.2.3 Kafka如何保证消息不丢?

  • 问题1

    • 3副本情况下,如何结合min.insync.replica 以及ack的配置,来保证写入kafka系统中的数据不丢失?

      • min.insync.replica=2,ack=-1
  • 问题2

    • 如果是5副本呢?

2.2.3 Kafka副本同步

LEO

  • Log End Offset,日志最末尾的数据

HW

  • ISR中最小的LEO作为HW
  • HW的消息为Consumer可见的消息

2.2.3 Kafka副本选举

  • Clean选举

    • 优先选取Isr 中的副本作为leader
    • 如果lsr中无可用副本,则 partition不可用
  • Unclean选举

    • 优先选取 Isr中的副本作为leader
    • 如果lsr中无可用副本,则选择其他存活副本

2.3.1 Kafka集群扩缩容

Kafka集群扩缩容之后的目标(迁移副本)

  • Topic维度

    • partition 在各个broker 之间分布是均匀的

      • 流量。每个broker网卡出入流磁盘均衡
    • 同一个partition 的replica 不会分布在一台broker

  • Broker 维度

    • Broker之间replica的数量是均匀的,负载均衡

3.1.2 Kafka集群扩容步骤

  • 扩容Broker节点

    • Leader副本写入成功,Producer即认为写成功
  • 计算均衡的Replica分布拓扑

    • 保证Topic的partition在 broker间分布均匀
    • 保证 Broker 之间Replica分布均匀
  • Controller负责新的副本分布元数据广播

  • Controller将新的leader/follower 信息广播给broker.

  • Broker负责新副本的数据同步

  • Broker上有需要同步数据的副本则进行数据同步

3.1.2 Kafka集群缩容步骤

  • 计算均衡的Replica分布拓扑

    • 保证Topic的partition在 broker间分布均匀
    • 保证 Broker之间Replica分布均匀
  • Controller负责新的副本分布元数据广播

  • Controller将新的leaderlfollower信息广播给broker

  • Broker负责新副本的数据同步

  • Broker上有需要同步数据的副本则进行数据同步

  • 下线缩容的Broker节点

  • 数据同步完毕之后下线缩容的Broker节点

3.1.2 Kafka集群扩缩容问题

  • 扩缩容时间长

    • 涉及到数据迁移,在生产环境中一次扩缩容可能要迁移TB甚至PB的数据
  • 扩缩容期间集群不稳定

    • 保证数据的完整性,往往会从最老的数据进行同步,这样会导致集群时刻处于从磁盘读取数据的状态,disk/net/cpu负载都会比较高
  • 扩缩容期间无法执行其他操作

    • 在一次扩缩容操作结束之前,无法进行其他运维操作(扩缩容)

2.4 Kafka未来演进之路

2.4.1 去除zookeeper依赖

依赖ZooKeeper存在问题

  • 元数据存取困难

    • 元数据的存取过于困难,每次重新选举的controller需要把整个集群的元数据重新restore,非常的耗时且影响集群的可用性。
  • 元数据更新网络开销大

    • 整个元数据的更新操作也是以全量推的方式进行,网络的开销也会非常大。
  • 强耦合违背软件设计原则

    • Zookeeper对于运维来说,维护Zookeeper也需要一定的开销,并且kaika强耦合与zk也并不好,还得时刻担心zk的宕机问题,违背软件设计的高内聚,低耦合的原则。
  • 网络分区复杂度高

    • Zookeeper本身并不能兼顾到broker与broker之间通信的状态,这就会导致网络分区的复杂度成几何倍数增长。
  • 并发访问zk问题多

    • Zookeeper本身并不能兼顾到broker与broker之间通信的状态,这就会导致网络分区的复杂度成几何倍数增长。

2.4.1.2 Kafka 依赖 KRaft

  • Process.Roles = Broker

    • 服务器在KRaft模式下充当Broker
  • Process.Roles = Controller

    • 服务器在KRaft模式下充当Controller
  • Process.Roles = Broker,Controller

    • 服务器在KRaft模式下充当Broker和Controllel
  • Process.Roles = null

    • 那么集群就假定是运行在ZooKeeper模式下。

2.4.5.1 Kafka运维/调优经验介绍

  • 单机吞吐
  • 参数配置
  • 指标可视化
  • 扩缩容优化

2.4.5.1.1 Kafka单机吞吐

字节实例

  • Kafka Version

    • 2.3.1
  • 机器配置

    • 40C 500GB 12*1TB 25GB
  • 写入配置

    • Ack = -1, replica = 3, in sync _replica = 3
    • 单条消息5 KB
  • 吞吐

  • 单机150MB/S

2.4.5.1.2 Kafka集群参数配置

  • zookeeper.session.timeout.ms = 30000

  • log.segment.bytes = 536870912

  • log.retention.hours = 36

  • log.retention.bytes = 274877906944. num.network.threads = 32

  • num.io.threads = 200

  • auto.create.topics.enable = false

    • 系统可掌控性(防止攻击、资源滥用)
  • auto.leader.rebalance.enable = false

    • 影响系统可用性
  • unclean.leader.election.enable = false

    • 数据的一致性
  • advertised.listeners = SASL_PLAINTEXT://:,PLAINTEXT://:

  • security.inter.broker.protocol = SASL_PLAINTEXT

5.1.3扩缩容优化

目标

  • Topic-Partition均匀分布在 Broker间
  • Broker间的 Replica是均匀的

5.1.4 指标可视化

03. pulsar详解

3.1 Pulsar 架构介绍

3.1.1 Pulsar Proxy

Pulsar Proxy的作用及应用场景

·部分场景无法知道Broker地址,如云环境或者Kubernetes环境. Proxy提供类似GateWay代理能力,解耦客户端和Broker, 保障Broker安全

Pulsar客户端连接集群的两种方式. Pulsar Client ->Broker Pulsar Client -> Proxy

3.1.2 Pulsar Broker

  • Pulsar Broker无状态组件,负责运行两个模块

    • Http服务器

      • 暴露了restful接口,提供生产者和消费者topic查找 api 调度分发器
  • 异步的tcp服务器,通过自定义二进制协议进行数据传输 Pulsar Broker 作为数据层代理

  • Bookie通讯

  • 作为Ledger代理负责和Bookie进行通讯

  • 流量代理

  • 消息写入Ledger存储到Bookie

  • 消息缓存在堆外,负责快速响应

3.1.3 Pulsar Storage

根据需求选择存储

  • Pulsar数据存储 Segment在不同存储中的抽象

    • 分布式Journal系统(Bookeeper)中为Journal/Ledger
    • 分布式文件系统(GFS/HDFS)中为文件
    • 普通磁盘中为文件
    • 分布式 Blob存储中为Blob
    • 分布式对象存储中为对象
  • 定义好抽象之后,即可实现多介质存储

  • L1(缓存):

    • Broker使用堆外内存短暂存储消息适用于Tail-Read读场景
  • L2(Bookkeeper):

    • Bookkeeper使用Qurom 写,能有效降低长尾,latency低
    • 适用于Catch-Up 较短时间内的较热数据
  • L3(S3等冷存):

    • 存储成本低,扩展性好
    • 适用于Catch-Up长时间内的冷数据

3.1.4 Pulsar lO 连接器

  • Pulsar lO分为输入(Input)和输出(Output)两个模块,输入代表数据从哪里来,通过Source 实现数据输入。输出代表数据要往哪里去,通过Sink 实现数据输出。
  • Pulsar提出了IO(也称为Pulsar Connector) ,用于解决 Pulsar与周边系统的集成问题,帮助用户高效完成工作。
  • 目前Pulsar lO支持非常多的连接集成操作:例如HDFS、Spark、Flink、Flume、ES、HBase等。

3.1.5 Pulsar Functions(轻量级计算框架)

  • Pulsar Functions是一个轻量级计算框架,提供一个部署简单、运维简单、API简单的FAAS 平台。
  • Pulsar Functions提供基于事件的服务,支持有状态与无状态的多语言计算,是对复杂的大数据处理框架的有力补充。
  • 使用Pulsar Functions,用户可以轻松地部署和管理function,通过function 从 Pulsar topic读取数据或者生产新数据到 Pulsar topic。

3.2 Bookkeepr介绍

3.2.1Bookeeper整体架构

读写:

3.2.2 Bookkeeper 基本概念

  • Ledger: BK的一个基本存储单元,BK Client的读写操作都是以Ledger为粒度的
  • Fragment: BK的最小分布单元(实际上也是物理上的最小存储单元),也是Ledger的组成单位,默认情况下一个Ledger会对应的一个 Fragment (一个 Ledger也可能由多个Fragment组成)
  • Entry:每条日志都是一个 Entry,它代表一个record,每条record都会有一个对应的entry id

3.2.3.1 Bookkeeper新建Ledger

Kafka:主从副本

这里:Quorum写(副本没有主从概念),降低长尾延时

  • Ensemble size(E):一个Ledger所涉及的Bookie集合
  • Write Quorum Size(Qw):副本数
  • Ack Quorum Size(Qa):写请求成功需要满足的副本数

3.2.3.2 Bookkeeper Ledger 分布

(右侧吞吐量高,节点多)

  • 从Bookie Pool挑选 Bookies构成Ensemble
  • Write Quorum Size决定发送给哪些Bookies
  • Ack Quorum Size决定收到几个Ack即为成功

3.2.4.2 Bookkeeper 写一致性

  • LastAddPushed,LAP
  • LastAddConfirmed,LAC
  • Fencing避免脑裂,加锁机制。只有一个Writer能写,保序的前提下Pipeline写

3.2.4.3 Bookkeeper读—致性

所有的Reader都可以安全读取 Entry ID小于或者等于LAC的记录,从而保证reader不会读取未确认的数据,从而保证了reader之间的一致性

3.2.4.1 Bookkeeper读写分离

  • 写入优化:

    • 写入时,不但写入到Journal中还会写入到缓存(memtable)中,定期会做刷盘(刷盘前会做排序,通过聚合+排序优化读取性能)
  • 读取优化:

    • 先读Memtable,没命中再通过索引读磁盘
    • Ledger Device中会维护一个索引结构,存储在RocksDB中,它会将(Ledgerld,Entryld)映射到(EntryLogld,文件中的偏移量)

3.2.5 Bookkeeper with pulsar

  • Topic-Partition:三个映射关系,逻辑上的映射关系

    • Topic 由多个partition 组成
    • Partition 由多个segment 组成
    • Segment 对应Ledger
  • 可以发现:

    • Partition <-> Broker 之间只是映射关系
    • Broker在扩缩容的过程中只需要更改映射即可

3.3 Pulsar 特性介绍

  • 生产模式
  • 消费模式
  • GEO Replication:集群之间、跨地域之间副本复制
  • 多租户能力
  • Plugin

3.3.1 Pulsar生产模式

3.4.1 集群HA & Scale-up

  • Topic <-> Bundle完成映射
  • Bundle 分配给Broker
  1. Lookup Topic
  2. Lookup Result
  3. Establish TCP Connection

3.5 Pulsar vs Kafka

  • 存储架构

    • 存储计算分离之后带来的优劣势
    • 多层架构,状态分离之后的优势
  • 运维操作

    • 应对突发流量变化,集群扩缩容是否便捷
    • 运维任务是否影响可用性
    • 集群部署是否灵活
  • 功能特性

    • 多语言&多协议
    • 多租户管理
    • 生产消费模式
  • 生态集成

3.5.1 存诸计算分离

  • 分层架构优势

    • 流量代理层和数据存储层解耦
    • 流量代理层无状态,可快速扩缩容(k8s等弹性平台)
    • 流量代理层可以对接海量的客户端连接
    • 存储层负责数据存储,可以使用多级存储
  • 存储层

    • 按照数据冷热进行存储介质区分,降低成本·历史数据可海量保存,数据无价
    • 可直接通过存储层接口读取数据,批式计算
  • 计算层

    • 对于写入的数据,可以做预处理,简单ETL
    • 可以做数据缓存,应对高扇出度场景
    • 无状态,扩缩容之后,能快速完成负载均衡Balance