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

168 阅读9分钟

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

消息队列概述

  • 消息队列应用场景

    • MQ 消息通道

MQ消息队列.png - EventBridge 事件总线

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

数据总线.png Data Platform 数据流平台

  • 提供流/批数据处理能力

  • 各类组件提供各类 Connect

  • 提供 Stream ing/function 能力

  • 根据数据 schema 灵活的进行数据预处理

  • 流数据平台.png

  • 主流消息队列介绍

    • RabbitMQ
    • RocketMQ
    • Kafka
    • Pulsar
RabbitMQRocketMQKafkaPulsar
推出时间2007201220102016
使用语言ErlangJavaScala/JavaJava
单机吞吐量一般较高
延迟一般
可用性(分片)高(主从架构)高(主从架构)非常高(分布式)非常高(分布式)
一致性较高
扩展性较高非常高

以上是4款比较流行的消息队列软件

Kafka 详解

  • Kafka 架构介绍

    • kafka架构介绍.png

    • zookeeper

      • zookeeper.png

      • 选举机制:Paxos机制

      • 提供一致性:写入(强一致性)、读取(会话一致性)

      • 提供可用性:一半以上节点存活即可读写

      • 提供功能:watch机制持久/临时节点能力

      • kafka 存储数据:

        • BrokerMeta 信息(临时节点)
        • Controller 信息(临时节点)
        • Topic 信息(持久化节点)
        • Config 信息(持久化节点)
    • Broker角色:

      • 若干个Broker 节点组成 kafka 集群
      • Broker 作为消息的接受模块,使用React 网络模块进行消息数据的接收
      • Broker 作为消息的持久化模块,进行消息的副本复制以及持久化(从图可以看到,leader和follower是是分布在两个 broker中,leader和 follower 之间进行消息的同步,保证数据的持久化)
      • Broker 作为高可用模块,通过副本间的 Failover 进行高可用保证
      • Broker角色.png
    • controller

      • 选举

        • broker 启动会尝试去 zk 中注册 controller 节点
        • 注册上 controller 节点的 broker 即为 controller
        • 其余 broker 会 watch controller 节点,节点出现异常则进行重新注册
        • controller选举.png
      • 作用

        • broker 重启/宕机时,负责副本的 Failover切换
        • Topic 创建/删除时,负责TopicMeta信息广播
        • 集群扩缩容时,进行状态控制
        • partition/Replica 状态机维护
        • controller 作用.png
      • coordinator介绍:

        • 负责 topic-partition<->consumer 的负责均衡
        • 根据不同的场景提供不同的分配策略
        • coordinator.png
  • Kafka 高可用

    • 高可用:

      • 副本同步机制:

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

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

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

      • OSR:

        • OutSyncReplica
        • 很久没有同步数据的副本
      • ISR:

        • 一直都在同步数据的副本
        • 可以作为热备进行切换的副本
      • kafka 写入 Ack 机制

        • Ack = 1:

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

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

          • ISR 中所有副本都成功,Producer 才认为写成功
      • kafka如何保证消息不丢?

        • Q1:

          • 3副本情况下,如何结合 m in.in syn c.replica 以及 ack 的配置,来保证写入的 kafka 系统中的数据不丢失?
          • 答案: m in.in syn c.replica 配置成 2 ,ack = -1,可以时刻保证你的系统中有两个副本是有完整数据的,你在进行切换的时候,势必会切换到一个数据多的副本上,可以保证数据的不丢失
        • Q2:

          • 如果是 5 副本呢?(与上面的一样)
      • kafka 副本同步:

        • LEO:logEndOffset ,日志最末尾的数据,文件中最后一条数据

        • HW:

          • ISR 中最小的 LEO 最为HW
          • HW 的消息为 Consumer 可见的消息
          • kafka副本同步.png
      • kafka副本选举:(重要的)

        • clean 选举:

          • 优先选取 ISR 中的副本作为 leader
          • 如果 ISR 中无可用的副本,则 partition 不可用(必须在 ISR 中选副本)
        • Unclean 选举

          • 优先选举 ISR中的副本作为leader
          • 如果 ISR 中无可用的副本,则选择其他存活副本
        • kafka副本选举.png

  • Kafka 集群扩缩容

    • kafka集群扩缩容之后的目标:

      • topic维度:

        • partition 在各个 broker 之间分布是均匀的
        • 同一个 partition 的replica 不会分布在一台 broker
      • broker 维度

        • broker 之间 replica 的数量是均匀的
      • kafka集群扩缩容.png

    • 扩容步骤:

      • 扩容 broker 节点

        • leader 副本写入成功,producer 即认为写成功
      • 计算均衡的 replica 分布拓扑

        • 保证 topic 的partition 在 broker 间分布均匀
        • 保证 broker 之间的 replica 分布均匀
      • controller 负责新的副本分布元数据广播

        • controller 将新的leader/follower 信息广播给 broker
      • broker 负责新副本的数据同步

        • broker上有需要同步数据的副本则进行数据同步
    • 缩容步骤:

      • 计算均衡的 replica 分布拓扑

        • 保证 topic 的partition 在 broker 间分布均匀
        • 保证 broker 之间 replica 分布均匀
      • controller 负责新的副本分布元数据广播

        • controller 将新的 leader/follower信息广播给 broker
      • broker 负责新副本的数据同步

        • broker 上有需要同步数据的副本则进行数据同步
      • 下线缩容的broker节点

        • 数据同步完毕之后下线缩容的broker节点
    • kafka 集群扩缩容问题”

      • 扩缩容时间长:涉及到数据迁移,在生产环境中一次扩缩容可能要迁移TB 甚至 PB 的数据
      • 扩缩容期间集群不稳定:保证数据的完整性,往往会从最老的数据进行同步,这样会导致集群时刻处于从磁盘中读取数据的状态,disk/net/cpu 负载都会比较高
      • 扩缩容期间无法执行其他操作:在一次扩缩容操作结束之前,无法进行其他运维操作(扩缩容)
  • Kafka 未来演进之路

    • kafka去除zk依赖

      • 依赖 zookeeper 存在问题:

        • 元数据存取困难:元数据的存取过于困难,每次重新选举的 controller 需要把整个集群的元数据重新 restore ,非常的耗时且影响集群的可用性
        • 元数据更新网络开销大:整个元数据的更新操作也是以全量推的方式进行,网络的开销也会非常大
        • 强耦合违背软件设计原则:zookeeper 对于运维来说,维护zookeeper 也需要一定的开销,并且 kafka 强耦合与zk也并不好,还得时刻担心宕机问题,违背软件设计的高聚合、低耦合的原则
        • 网络分区复杂度高:zookeeper 本身并不能兼顾到broker 与 broker 之间通信的状态,这就会导致网络分区的复杂度成几何倍数增长
        • 并发访问 ZK 问题多:zookeeper 本身并不能兼顾到broker 与 broker 之间通信的状态,这就会导致网络分区的复杂度成几何倍数增长
    • kafka 依赖 KRaft:

      • process.Roles = Broker:服务器在 Kafka 模式下充当 Broker
      • process.Roles = Controller:服务器在 Kafka 模式下充当 Controller
      • Process.Roles = Broker,Controller:服务器在 KRaft 模式下充当 Broker 和 Controller
      • Process.Roles = null:那么集群就假定是运行在 Zookeeper 模式下
      • kafka 依赖 KRaft.png
  • Kafka 运维/调优经验介绍(字节:2.3.1)

    • 单机吞吐

      • 单机吞吐.png
    • 参数配置:

      • kafka集群参数配置.png
    • 扩缩容优化

扩缩容优化.png - 指标可视化

    -   ![指标可视化.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/965bdcfbccbb4986bb7dfed71c17f8c4~tplv-k3u1fbpfcp-watermark.image?)

Pulsar 详解

  • Pulsar 架构介绍(具备了kafka不具备的功能)

    • pulsar 架构介绍.png

    • pulsar proxy:

      • pulsar 客户端连接集群的两种方式:

        • pulsar client —>broker
        • pulsar client->proxy
      • pulsar proxy 的作用及应用场景

        • 部分场景无法知道 broker 地址,如云环境
        • proxy 提供类似 GateWay 代理能力,解耦客户端和 broker ,保障 broker 安全
        • pulsar proxy.png
    • pulsar broker:

      • pulsar broker.png

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

        • Http 服务器

          • 暴露了 restful 接口,提供生产者和消费者 topic 查找 api
        • 调度分发器

          • 异步的 tcp 服务器,通过自定义二进制协议进行数据传输
      • Pulsar Broker 作为数据层代理

        • Bookie通讯

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

          • 消息写入 Ledger 存储到 Bookie(Java写的)进行持久化存储
          • 消息缓存在堆外,负责快速响应
      • pulsar storage

        • pulsar storage.png

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

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

          • L1(缓存):

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

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

            • 存储成木低;扩展性好
            • 适用于 Catch-Up 长时间内的冷数据
      • pulsar function (轻量级计算框架)

        • pulsar function (轻量级计算框架)1.png
        • pulsar function (轻量级计算框架)2.png
  • bookeeper整体架构

    -   在内存中进行一个聚合,之后在写入磁盘中
    
    • bookkeeper 基本概念:

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

bookkeeper 基本概念.png - bookkeeper 新建 Ledger

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

bookkeeper Ledger 分布

bookkeeper Ledger 分布.png - 从 Bookie Pool挑选 Bookies 构成 Ensemble - Write Quorum Size 决定发送给哪此 Bookies - Ack Quorum Size 决定收到几个 Ack 即为成功

bookkeeper 写一致性

bookkeeper 写一致性.png bookkeeper读一致性

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

bookkeeper读写分离.png

写入优化

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

读取优化

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

bookkeeper with pulsar bookkeeper with pulsar.png

Topic-Partition:

Topic 由多个 partition 组成 Partition 由多个 segment 组成 Segment 对应 Ledger

可以发现:

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

  • Pulsar 特性介绍

    • pulsar生产模式.png
    • pulsar 消费模式.png
  • Pulsar vs Kafka

pulsar kafka.png

存储计算分离.png

周边和生态

  • 周边生态概览

    • 周边生态概览.png
  • Pulsar IO

    • pulsar IO.png
  • Kafka Schema

    • kafka schema.png
  • Pulsar SQL

    • pulsar & SQL.png