热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ApachePulsar调研

点击上方“芋道源码”,选择“设为星标”管她前浪,还是后浪?能浪的浪,才是好浪!每天10:33更新文章ÿ

点击上方“芋道源码”,选择“设为星标”

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 10:33 更新文章,每天掉亿点点头发...

源码精品专栏

 
  • 原创 | Java 2021 超神之路,很肝~

  • 中文详细注释的开源项目

  • RPC 框架 Dubbo 源码解析

  • 网络应用框架 Netty 源码解析

  • 消息中间件 RocketMQ 源码解析

  • 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析

  • 作业调度中间件 Elastic-Job 源码解析

  • 分布式事务中间件 TCC-Transaction 源码解析

  • Eureka 和 Hystrix 源码解析

  • Java 并发源码

来源:yinzige.com/2020/04/
24/pulsar-survey/

  • Apache Pulsar

  • 1. Kafka 概述

    • 1.1 现存问题

    • 1.3 优点

    • 1.4 缺点

  • 2. Pulsar 架构

    • 2.1 Pulsar VS Kafka

    • 2.2 Pulsar 架构

    • 2.3 多租户与 Topic Lookup

    • 2.4 Produce / Consume 策略

  • 3. Bookkeeper 架构

    • 3.1 概念

    • 3.2 架构

    • 3.3 写流程

    • 3.4 读流程

  • 4. 水平扩容

    • 4.1 水平扩展 Broker

    • 4.2 水平扩展 Bookie

  • 5. Pulsar Consistency

    • 5.1 一致性机制

    • 5.2 Bookie Auto Recovery:Ensemble Change

    • 5.3 Broker Recovery:Fencing

  • 6. Distributed Log 与 Raft

    • 6.1 概念对比

    • 6.2 流程对比

    • 6.3 总结

  • 7. 总结

    • 7.1 Pulsar 的优点

    • 7.2 Pulsar 的缺点

faaf02a7972bb1fa13c4cd769a9b1732.png


简要总结下对 Pulsar 的调研。

Apache Pulsar

内容:

  • Kafka : 优缺点。

  • Pulsar : 多租户,Topic Lookup,生产消费模式

  • Bookkeeper : 组件概念与读写流程

  • Horizontal Scale : Broker 或 Bookie 的横向扩展

  • Consistency : Broker 或 Bookie crash 后保证日志一致性

  • Distributed Log & Raft 算法

  • 总结

推荐下自己做的 Spring Boot 的实战项目:

https://github.com/YunaiV/ruoyi-vue-pro

1. Kafka 概述

1.1 现存问题

主要问题:

  • 负载均衡需人工介入:手动按异构配置的 broker 对应生成 assignment 执行计划。

  • 故障恢复不可控:broker 重启后需复制分区新数据并重建索引,其上的读写请求转移到其他 broker,流量激增场景下可能会导致集群雪崩。

其他问题:

  • 跨数据中心备份需维护额外组件:MirrorMaker 官方也承认鸡肋,做跨机房的冗余复制依赖第三方组件如 uber 的 uReplicator

注:已脱敏。

1.3 优点

  • 生态成熟,易与 Flink 等现有组件集成。

  • 可参考资料多,完善的官方文档和书籍。

  • 模型简单易上手:partition 有 replication,以 segment 和 index 方式存储。

1.4 缺点

计算与存储耦合

  • 存储节点有状态:读写只能走 Partition Leader,高负载集群中 Broker 重启容易出现单点故障,甚至雪崩。

  • 手动负载均衡:集群扩容必须手动 Assign Partitions 到新 Broker,才能分散读写的负载。

漫画对比:https://jack-vanlightly.com/sketches/2018/10/2/kafka-vs-pulsar-rebalancing-sketch

推荐下自己做的 Spring Cloud 的实战项目:

https://github.com/YunaiV/onemall

2. Pulsar 架构

2.1 Pulsar VS Kafka


PularKafka
数据集合Topic, PartitionTopic, Partition
存储节点及读写组件Bookkeeper BookieBroker

Pulsar BrokerClient SDK
数据存储单元Partition -> Ledgers -> FragmentsPartition -> Segments
数据一致性保证Ensemble Sizemetadata.broker.list

Write Quorum Size(QW)Replication Factor

Ack Quorum Size(QA)request.required.acks

注&#xff1a;(QW&#43;1)/2 <&#61; QA <&#61; QW <&#61; Ensemble Size <&#61; Bookies Count

2.1.1 数据集合

  • Kafka&#xff1a;topic 切分为多个 partitions&#xff0c;各 partition 以目录形式在 leader broker 及其多副本 brokers 上持久化存储。

  • Pulsar&#xff1a;同样有多个 partitions&#xff0c;但一个 partition 只由一个 broker 负责读写&#xff08;ownership&#xff09;&#xff0c;而一个 partition 又会均匀分散到多台 bookie 节点上持久化存储。

2.1.2 存储节点

  • Kafka&#xff1a;直接持久化到 broker&#xff0c;由 Client SDK 直接读写。

  • Pulsar&#xff1a;分散持久化到 bookie&#xff0c;由 broker 内嵌的 bookkeeper Client 负责读写。

2.1.3. 一致性保证

  • Kafka&#xff1a;通过多 broker 集群&#xff0c;每个 partition 多副本&#xff0c;producer 指定发送确认机制保证。

  • Pulsar&#xff1a;通过多 broker 集群&#xff0c;broker Quorum Write 到 bookie&#xff0c;返回 Quorum ACK 保证。

2.2 Pulsar 架构

d1d72ba80631f5bb8f9f6ffaf82e8912.png

2.3 多租户与 Topic Lookup

2.3.1 多租户

  • topic 分三层&#xff1a;persistent://tenant/namespace/topic&#xff0c;对应划分为 department -> app -> topics&#xff0c;以 namespace 为单位进行过期时间设置&#xff0c;ACL 访问鉴权控制。

  • 优点&#xff1a;按租户进行 topic 资源隔离&#xff0c;并混部在同一集群中&#xff0c;提高集群利用率。

2.3.2 Topic 分配

Broker 的 LoadManager 线程
  • Leader&#xff1a;即 Broker Leader&#xff0c;类似 Kafka Controller&#xff0c;汇总所有 Broker 的负载&#xff0c;合理地分配 topic 分区。

  • Wroker&#xff1a;等待分配 bundle 内的所有 topic partition

bundle 与 ownership
  • 以 Namespace 为单位在 ZK 维护 bundle ring&#xff08;broker 的数量 2~3 倍&#xff09;&#xff0c;topic 分区按 hash(topic_partition)%N 落到 bundle 中。

  • Broker 唯一绑定到 bundle&#xff0c;就对 bundle 内的所有 topic partition 持有 ownership&#xff0c;用于 Broker Recovery 保证高可用。

afd93139f6ef725263d16c2b99245e4b.png
Topic 分配流程
  • 上报负载&#xff1a;LoadManager Worker 负责向 ZK 汇报负载指标

    zk> get /loadbalance/brokers/localhost:8080{ "pulsarServiceUrl": "pulsar://localhost:6650", "cpu": { "usage": 23, "limit": 50 }, "memory": { "usage": 1, "limit": 10 }, "msgThroughputIn": 100, "msgThroughputOut": 100}

  • bundle 为单位分配&#xff1a;LoadManager Leader 汇总其他 Brokers 的负载&#xff0c;根据负载分配 bundle

    zk> get /loadbalance/leader{"serviceUrl":"http://localhost:8080","leaderReady":false}

  • 分配结果&#xff1a;

    zk> ls /namespace/public/default[0x00000000_0x40000000, 0x40000000_0x80000000, 0x80000000_0xc0000000, 0xc0000000_0xffffffff]zk> get /namespace/public/default/0x80000000_0xc0000000{"nativeUrl":"pulsar://localhost:6650","httpUrl":"http://localhost:8080","disabled":false}

设计优点

不同于 kafka 将所有 topic ISR 等元数据记录到 zk&#xff0c;pulsar 只记录 topic 的分区数&#xff0c;不记录 topic 到 broker 的映射关系&#xff0c;zk 元数据数量极少&#xff0c;所以支持百万量级 topic

zk> get /admin/partitioned-topics/public/default/persistent/partitioned-topic-1{"partitions":2}

2.3.3 Topic Lookup

  • Client 向任一 BrokerA 发起 Lookup 请求&#xff0c;如 persistent://public/default/test-topic-1

  • BrokerA 计算 default namespace 下 hash(topic_partition)%N 的值&#xff0c;得到该 topic partition 对应的 bundle&#xff0c;从而查出 ownership BrokerX

  • BrokerA 返回 owner BrokerX 地址。

2.4 Produce / Consume 策略

2.4.1 三种写路由策略

  • RoundRobinPartition&#xff08;默认&#xff09; &#xff1a;以 batching 为单位&#xff0c;通过轮询将消息均匀发给 brokers&#xff0c;以获得最大吞吐。

  • SinglePartition

    • 有 KEY 则写固定分区&#xff0c;类似 hash(key) mod len(partitions) 写到指定分区。

    • 无 KEY 则随机选一个分区&#xff0c;写入该 producer 的所有消息。

  • CustomPartition &#xff1a;用户可自定义针对具体到消息的分区策略&#xff0c;如 Java 实现 MessageRouter 接口。

2.4.2 四种读下发策略

  • Exclusive &#xff08;默认&#xff09; &#xff1a;独占消费&#xff0c;一对一&#xff0c;保证有序消费&#xff0c;能批量 ACK&#xff0c;是 Failover 特例&#xff0c;不保证高可用。

  • Failover &#xff1a;故障转移消费&#xff0c;一对一&#xff0c;备选多&#xff0c;保证有序消费&#xff0c;消费者高可用&#xff0c;能批量 ACK&#xff0c;保证高可用。

  • Shared &#xff1a;共享消费&#xff0c;多对多

    704a305d2b047fd8e4b050a82747ca58.png
    • Round Robin 分发消息&#xff0c;类似 Consumer Group 但不保证有序消费。

    • 只能逐条 ACK&#xff1a;Consumer crash 时才能精确控制消息的重发。

    • 水平扩展 Consumer 直接提读吞吐。不像 kafka 必须先扩 Partition 才能扩 Consumer

  • Key_Shared &#xff1a;按 KEY 共享消费&#xff0c;多对多&#xff0c;Exclusive 和 Shared 的折中模式。

    9f32ea282414d75cbcaf6fca95d8247b.png
    • KEY hash 相同的消息会被相同 consumer 消费&#xff0c;保证有序消费。

    • 只能逐条 ACK

    • 水平扩展 Consumer 提高读吞吐。

2.4.3 Pull & Push 可选请求模式

  • Consumer 可以同步或异步 p Receive 消息。

  • Consumer 可以本地注册 MessageListener 接口来等待 Broker Push 消息。

2.4.4 Consume ACK 与 unACK

  • 逐条 ACK、批量 ACK

  • 取消 ACK&#xff1a;consumer 消费出错可请求重新消费&#xff0c;发送取消 ACK 后 broker 会重发消息。

    • exclusive, failover&#xff1a;只能取消上一次提交的 ACK&#xff0c;单个 consumer 可控回滚。

    • shared, key_shared&#xff1a;类比 ACK&#xff0c;consumers 只能取消上一条发出的 ACK

__consumer_offsets 机制类似 &#xff0c;Broker 收到各消费者的 ACK 后&#xff0c;会更新 Consumer 的消费进度 cursor&#xff0c;并持久化到特定的 ledger 中。

2.4.5 Data Retention

  • 默认积极保留&#xff1a;最慢的 subscription 堆积的消息都不能被删除&#xff0c;最坏的情况是某个 subscription 下线后&#xff0c;cursor 依旧会保留在 message streaming 中&#xff0c;会导致消息过期机制失效。

  • 消息过期&#xff1a;时间或大小两个维度设置限制&#xff0c;但只对积极保留之前的消息生效

  • TTL&#xff1a;强制移动旧慢 cursor 到 TTL 时间点&#xff0c;若 TTL &#61;&#61; Retention&#xff0c;则与 kafka 一样强制过期

edd24a99676a55ecea2e0be3a8dc3149.png

两个指标

  • Topic Backlog&#xff1a;最慢的 subscription 的 cursor 到最新一条消息之间的消息数量。

  • Storage Size&#xff1a;topic 总空间。

    • 按 segment 粒度删除&#xff0c;以 Last Motify Time 是否早于 Retention 为标准过期&#xff0c;与 kafka 一致

    • 注&#xff1a;bookie 并非同步过期&#xff0c;空间释放是后台进程定期清理

3. Bookkeeper 架构

append-only 的分布式 KV 日志系统&#xff0c;K 是 (Ledger_id, Entry_id) 二元组&#xff0c;V 是 (MetaData, RawData) 二进制数据。

3.1 概念

3.1.1 特性

  • 高效写&#xff1a;append-only 磁盘顺序写。

  • 高容错&#xff1a;通过 bookie ensemble 对日志进行冗余复制。

  • 高吞吐&#xff1a;直接水平扩展 bookie 提高读写吞吐。

3.1.2 Ensemble Size / Ensembles / Write Quorum / ACK Quorum / Segment(Ledger) / Fragment

  • Ensemble Size&#xff1a;指定一段 日志要写的 bookies 数量。

  • Ensembles&#xff1a;指定写一段 日志的目标 bookies 集合。

  • Write Quorum&#xff1a;指定一条 日志要写 的 bookie 数量。

  • ACK Quorum&#xff1a;指定一条 日志要确认已写 入的 bookie 数量。

  • Segment / Ledger&#xff1a;要写入的一段 日志。

  • Fragment&#xff1a;写入的一条 日志。

ee2137d7973f086ca58b50357ceb9c4d.png

3.1.3 结论

  • Client 会以 Round Robin 的策略挑选出 bookie&#xff0c;依次顺延写 entry

  • Client 只等待 ACK Quorum 个 broker 返回 Append ACK 就认为写成功。

  • 一个 Segment / Ledger 包含多个 Fragment

  • Fragment 内的 entry 呈带状连续 分布在 Ensembles Bookies 上。

  • 一个周期内&#xff0c;一台 Bookie 会存储不连续(EnsembleSize - WriteQuorum) 条 Entry

3.2 架构

三个组件

  • zk / etcd&#xff1a;强一致性元数据存储

    • 元数据存储&#xff1a;ledger 元数据。

    • 服务发现&#xff1a;bookie 的注册中心&#xff0c;bookie 互相发现&#xff0c;client 读取集群全部 bookie 地址。

  • Bookie&#xff1a;存储节点&#xff0c;只允许 ADD / READ 两个操作&#xff0c;不保证一致性&#xff0c;不保证可用性 &#xff0c;功能简单。

  • Client&#xff1a;实现冗余复制的逻辑&#xff0c;保证数据的一致性&#xff0c;实现复杂且最重要。

05a2da008b65407869d5f5d0be3c99fd.png

3.3 写流程

3.3.1 三种文件

  • Journal WAL

    • 概念&#xff1a;用于持久化存储 bookie 操作 ledger 的事务日志&#xff0c;接收来自多个 Ledger Client 写入的不同 ledger entries&#xff0c;直接 高效地 append 到内存&#xff0c;随后 fsync 顺序写磁盘&#xff0c;延迟低。

    • 清理&#xff1a;当 Write Cache 完成 Flush 落盘后自动删除。

  • Entry Logs

    • 概念&#xff1a;真正落盘的日志文件&#xff0c;有序保存不同 ledger 的 entries&#xff0c;并维护 Write Cache 加速热日志的查找。

    • 清理&#xff1a;bookie 后台 GC 线程定期检查其关联的 ledgers 是否在 zk 上已删除&#xff0c;若已删除则自动清理。

  • Index Files

    • 概念&#xff1a;高效顺序写的副作用是&#xff0c;必须在外围维护 (ledger_id, entry_id)Entry_Log 的映射索引&#xff0c;才能实现高效读&#xff0c;故 Flush Cache 时会分离出索引文件。

    • 实现&#xff1a;可选 RocksDB 和文件存储索引。

3.3.2 ADD 操作

  • Clients 混乱地给 Bookie 发来不同 ledger 的日志。

  • Bookie 往追加写 Journal&#xff0c;同时向 Write Cache 有序写&#xff08;Write Cache 内部使用 SkipList 实现动态有序&#xff0c;同时保证读写都高效&#xff09;

  • WriteCache 写满后 Flush 分离出 index 文件和落盘的日志文件。

  • 删除旧 Journal&#xff0c;创建新 Journal 继续追加写&#xff0c;如此循环。

072e4167e43dd944459747adb81c8fe0.png

3.3.3 结论

broker 内部为每个 ledger 持久化了其存储的 entry logs&#xff0c;并建立索引提高读效率。

3.4 读流程

Client 发来 (ledger_id, entry_id) 的 KEY

  • 热 KEY&#xff1a;在 Write Cache 中则直接返回。

  • 冷 KEY&#xff1a;读取 ledger_id 对应的 index 文件&#xff0c;根据 index 找出 entry_id 对应的 entry log 再返回。

3.4.1 读被均摊

如同轮询写&#xff0c;Cleint 也会轮询 Ensembles 均摊读取&#xff0c;同样不存在 leader 读瓶颈。

3.4.2 读有预期

若某个 Bookie 读响应确实很慢&#xff0c;Client 会向其他副本 Bookie 发起读请求&#xff0c;同时等待&#xff0c;从而保证读延时低。

3.4.3 读结果无序

Client 往 bookie 写是轮询无序地写&#xff0c;故从 Ensembles 中读到是消息是无序的&#xff0c;需在 Client 端自行按 entry_id 重新排序&#xff0c;以保证有序响应。

4. 水平扩容

4.1 水平扩展 Broker

新 Broker 加入集群后&#xff0c;Broker Leader 会将高负载 Broker 的部分 topic ownership 转移给新 Broker&#xff0c;从而分摊读写压力。

4.2 水平扩展 Bookie

新 Bookie 加入集群后&#xff0c;Broker 通过 ZK 感知到&#xff0c;并将 ledger 的新 entry log 写到新 Bookie&#xff0c;提高存储层的读写吞吐、存储容量。

cb179a97a5110eff2e6fc73017ca7e29.png

5. Pulsar Consistency

5.1 一致性机制

日志的冗余复制、一致性保证均由 Bookkeeper Client 实现。

5.1.1 冗余副本

由如上的 Eensembles 的 QW 和 QA 的多副本写&#xff0c;保证每条日志确实持久化到了 bookie 中。

5.1.2 一致性机制

滑动窗口&#xff1a;[0, ..., READABLE ... LAC], [LAC&#43;1, ... WAIT_QUOROM ..., LAP]

  • LAP&#xff08;Last Add Pushed&#xff09;&#xff1a;Client 发出的最后一条 entry_id&#xff08;从 0 自增的正整数&#xff09;

  • LAC&#xff08;Last Add Confirmed&#xff09;&#xff1a;Client 收到的最后一条 ACK 的 entry_id&#xff0c;是一致性的边界。

实现一致性的三个前置条件&#xff1a;

  • 写 ledger 只能以 Append-Only 方式追加写&#xff0c;写满后变为 Read-Only

  • 一个 Ledger 同一时间只会有一个 Client 在写。

  • LAC 必须按照 LAP 的顺序&#xff0c;依次进行 ACK 确认&#xff1a;保证 LAC 作为一致性边界&#xff0c;前边的日志可读&#xff0c;后边的日志等待多副本复制。

cef9ede2df0f3eeda492ef62bdf1f4ae.png

5.2 Bookie Auto Recovery&#xff1a;Ensemble Change

5.2.1 场景

bookie crash 下线后&#xff0c;需恢复副本数量。

5.2.2 流程

  • 存在 Leader Bookie 5 作为 Daemon Auditor&#xff0c;不断向其他 Bookies 发送心跳保活。

  • Auditor 发现 Bookie 4 超时&#xff0c;读取 zk 发现 ledger x 的 [0, 7) entry_id 区间需要从 4 转移到新 Bookie

  • 找出负载较小的 Bookie 6&#xff0c;并根据 Ensembles 发现冗余数据分布在 {B1, B2, B3, B5}

  • 按轮询均摊复制读压力的方式&#xff0c;将 entry log 逐一复制到 Bookie 6

  • 复制完毕后修改 ZK 元数据&#xff0c;将 LAC0 的副本 4 替换为 6

07a616c76529a1edd4951f6cd2d8be86.png

5.2.3 结论&#xff1a;Bookie 故障秒级恢复

  • 写请求快速转移&#xff1a;

    Bookie 6 加入 Ensembles 后&#xff0c;直接代替 Bookie 4 继续 Append 日志。因为副本数恢复是各个 Ensembles 内部各节点的 Auditor 线程后台异步复制&#xff0c;不会导致 Client 的写中断&#xff0c;整个 Recovery 过程对 Client 几乎透明。

  • LAC 分界线记录 Ensemble Change 历史&#xff1a;

    在 ZK 的 ledger metadata 中&#xff0c;会记录每次 Recovery 导致的 ensembles 更新&#xff0c;即记录了 ledger 各 entry log 区间的分布情况。如下元数据记录了 ledger16 在 LAC46 处&#xff0c;Bookie 3183 下线&#xff0c;随后 Bookie 3182 上线从 LAC47 处继续处理请求&#xff1a;

    > get /ledgers/00/0000/L0016ensembleSize: 3quorumSize: 2ackQuorumSize: 2lastEntryId: -1state: OPENsegment { ensembleMember: "10.13.48.57:3185" ensembleMember: "10.13.48.57:3184" ensembleMember: "10.13.48.57:3183" firstEntryId: 0}segment { ensembleMember: "10.13.48.57:3185" ensembleMember: "10.13.48.57:3184" ensembleMember: "10.13.48.57:3182" firstEntryId: 47}

注意&#xff1a;右上可看出 ZK 中各 ledger 的元数据硬编码了 Bookie 的 IP&#xff0c;容器部署时若 Bookie 重启后 IP 变化&#xff0c;会导致旧 Ledger 的该副本作废&#xff0c;故在 k8s 上部署时应选择 DaemonSet 或 StatefulSet

5.3 Broker Recovery&#xff1a;Fencing

5.3.1 场景

Broker crash&#xff0c;或 Broker 与 ZK 出现网络分区导致脑裂&#xff0c;需进行 partition ownership 转移。

5.3.2 流程

  • Broker1 心跳超时后&#xff0c;ZK 将 topic partition 的 ownership 转移到 Broker2

  • Broker2 向 Ensemble 发起 Fencing ledger_X 请求&#xff0c;Bookies 纷纷将 ledger_X 置为 Fencing 不可写状态。

  • Broker1 写数据失败收到 FenceException&#xff0c;说明该 partition 已被 Broker 接管&#xff0c;主动放弃 ownership

  • Client 收到异常后与 Broker1 断开连接&#xff0c;进行 Topic Lookup 与 Broker2 建立长连接。

  • 同时&#xff0c;Broker2 对 ledger_X LAC1 之后的 entry log 依次逐一进行 Forwarding Recovery&#xff08;若 unknow 状态的 entry 副本数实际上已达到 WQ&#xff0c;则认为该 entry 写成功&#xff0c;LAC1 自增为 LAC2&#xff09;

  • Broker2 更新 ledger_X 的 metadata&#xff0c;将其置为 CLOSE 状态&#xff0c;再创建新 ledger&#xff0c;继续处理 Client 的写请求。

919c83487f76dc72ea55cc40b5820eca.png

5.3.3 结论&#xff1a;Broker 故障秒级恢复

  • 不复用旧 ledger&#xff0c;降低复杂度 若复用旧 ledger_X&#xff0c;必须保证所有 ensemble 的 LAC 一致&#xff0c;同时涉及尾部 entry 的强一致复制&#xff0c;逻辑复杂。直接 CLOSE 能保证旧 ledger 不会再被写入。

  • Recovery 逻辑简单&#xff0c;耗时短 在 Client 的视角&#xff0c;只需等待两个过程&#xff1a;

    等待结束后&#xff0c;直接往新 Broker 的新 ledger 上追加写数据&#xff0c;Broker 不参与任何数据冗余复制的流程&#xff0c;所以是无状态的&#xff0c;可以直接水平扩展提升以提升吞吐。

    • ZK 进行 partition ownership 的转移。

    • 新 Broker 对 UNKNOWN 状态的尾部 entry 进行 Forwarding Recovery

6. Distributed Log 与 Raft

6.1 概念对比

概念RaftDL
roleLeader 与 FollowersWriter (broker) 与 Bookies
failovertermledger_id
replicationMajority AppendEntries RPCQuorum Write
consistencyLast Committed IndexLast Add Confirmed&#xff08;LAC&#xff09;
brain splitMajority VoteBroker Fencing

6.2 流程对比

66d4e2d380025ea42d4ea6a960d1eed8.png

6.3 总结

  • LAC 与 LAP 的存在&#xff0c;使 entry 能以内嵌顺序元数据的方式&#xff0c;均匀分散存储到各台 bookie 中。

  • DL 与 Raft 不同之处在于&#xff1a;

    各 bookie 节点的数据不是从单个节点异步复制而来&#xff0c;而是由 Client 直接轮询分发。

    • 为保证 bookie 能快速 append 日志&#xff0c;bookkeeper 设计了 Journal Append-only 顺序写日志机制。

    • 为保证 bookie 能快速根据 (lid, eid) 读取消息(entry)&#xff0c;bookkeeper 设计了 Ledger Store

因此&#xff0c;各 bookie 存储节点的身份是平等的&#xff0c;没有传统一致性算法的 Leader 和 Follower 的概念&#xff0c;完美避开了读写只能走 Leader 导致 Leader 容易成为单点瓶颈的问题。同时&#xff0c;能直接添加新 Bookie 提升读写吞吐&#xff0c;并降低其他旧 Bookie 的负载。

7. 总结

7.1 Pulsar 的优点

直接解决 Kafka 容器平台现有的手工扩容、故障恢复慢的问题。

  • 稳定性可用性高&#xff1a;秒级 Broker / Bookie 的快速故障恢复。

  • 水平线性扩容&#xff1a;存储与计算分离&#xff0c;可对 Broker 扩容提升读写吞吐&#xff0c;可对 Bookie 扩容降低集群负载并提升存储容量。

  • 扩容负载均衡&#xff1a;Bookie 扩容后新的 ledger 会在新 Bookie 上创建&#xff0c;自动均摊负载。

7.2 Pulsar 的缺点

  • 概念多&#xff0c;系统复杂&#xff0c;隐藏 bug 修复门槛高。

  • 背书少&#xff0c;国内仅腾讯金融和智联招聘在使用。



欢迎加入我的知识星球&#xff0c;一起探讨架构&#xff0c;交流源码。加入方式&#xff0c;长按下方二维码噢&#xff1a;

1b8477eddfd88fb7ea3d0b7b0dd86864.png

已在知识星球更新源码解析如下&#xff1a;

79902493d3461100e0626a39a4d70d88.png

7efec7f77c533e742120e288b9cce376.png

a7072f92c51800b4e26420a0b68551db.png

8f77584bd8cefdbabbe611f77b7ad93c.png

最近更新《芋道 SpringBoot 2.X 入门》系列&#xff0c;已经 101 余篇&#xff0c;覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例&#xff0c;以及超 4W 行代码的电商微服务项目。

获取方式&#xff1a;点“在看”&#xff0c;关注公众号并回复 666 领取&#xff0c;更多内容陆续奉上。

文章有帮助的话&#xff0c;在看&#xff0c;转发吧。
谢谢支持哟 (*^__^*&#xff09;


推荐阅读
  • 2019年后蚂蚁集团与拼多多面试经验详述与深度剖析
    2019年后蚂蚁集团与拼多多面试经验详述与深度剖析 ... [详细]
  • 本文详细介绍了Java代码分层的基本概念和常见分层模式,特别是MVC模式。同时探讨了不同项目需求下的分层策略,帮助读者更好地理解和应用Java分层思想。 ... [详细]
  • 秒建一个后台管理系统?用这5个开源免费的Java项目就够了
    秒建一个后台管理系统?用这5个开源免费的Java项目就够了 ... [详细]
  • 提升 Kubernetes 集群管理效率的七大专业工具
    Kubernetes 在云原生环境中的应用日益广泛,然而集群管理的复杂性也随之增加。为了提高管理效率,本文推荐了七款专业工具,这些工具不仅能够简化日常操作,还能提升系统的稳定性和安全性。从自动化部署到监控和故障排查,这些工具覆盖了集群管理的各个方面,帮助管理员更好地应对挑战。 ... [详细]
  • 修复一个 Bug 竟耗时两天?真的有那么复杂吗?
    修复一个 Bug 竟然耗费了两天时间?这背后究竟隐藏着怎样的复杂性?本文将深入探讨这个看似简单的 Bug 为何会如此棘手,从代码层面剖析问题根源,并分享解决过程中遇到的技术挑战和心得。 ... [详细]
  • RocketMQ在秒杀时的应用
    目录一、RocketMQ是什么二、broker和nameserver2.1Broker2.2NameServer三、MQ在秒杀场景下的应用3.1利用MQ进行异步操作3. ... [详细]
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • 从0到1搭建大数据平台
    从0到1搭建大数据平台 ... [详细]
  • 在当今的软件开发领域,分布式技术已成为程序员不可或缺的核心技能之一,尤其在面试中更是考察的重点。无论是小微企业还是大型企业,掌握分布式技术对于提升工作效率和解决实际问题都至关重要。本周的Java架构师实战训练营中,我们深入探讨了Kafka这一高效的分布式消息系统,它不仅支持发布订阅模式,还能在高并发场景下保持高性能和高可靠性。通过实际案例和代码演练,学员们对Kafka的应用有了更加深刻的理解。 ... [详细]
  • REST与RPC:选择哪种API架构风格?
    在探讨REST与RPC这两种API架构风格的选择时,本文首先介绍了RPC(远程过程调用)的概念。RPC允许客户端通过网络调用远程服务器上的函数或方法,从而实现分布式系统的功能调用。相比之下,REST(Representational State Transfer)则基于资源的交互模型,通过HTTP协议进行数据传输和操作。本文将详细分析两种架构风格的特点、适用场景及其优缺点,帮助开发者根据具体需求做出合适的选择。 ... [详细]
  • 在JavaWeb项目架构中,NFS(网络文件系统)的实现与优化是关键环节。NFS允许不同主机系统通过局域网共享文件和目录,提高资源利用率和数据访问效率。本文详细探讨了NFS在JavaWeb项目中的应用,包括配置、性能优化及常见问题的解决方案,旨在为开发者提供实用的技术参考。 ... [详细]
  • 本文深入解析了Spring Cloud路由网关Zuul的核心功能及其典型应用场景。通过对方志朋老师教材的学习和实践,详细探讨了Zuul在微服务架构中的重要作用,包括请求路由、过滤器链管理以及服务动态扩展等关键特性。同时,结合实际案例,展示了Zuul在高并发和复杂业务场景下的应用优势,为读者提供了全面的技术参考。 ... [详细]
  • 近年来,BPM(业务流程管理)系统在国内市场逐渐普及,多家厂商在这一领域崭露头角。本文将对当前主要的BPM厂商进行概述,并分析其各自的优势。目前,市场上较为成熟的BPM产品主要分为两类:一类是综合型厂商,如IBM和SAP,这些企业在整体解决方案方面具有明显优势;另一类则是专注于BPM领域的专业厂商,它们在特定行业或应用场景中表现出色。通过对比分析,本文旨在为企业选择合适的BPM系统提供参考。 ... [详细]
  • 如何撰写初级和高级前端开发者的专业简历
    如何撰写初级和高级前端开发者的专业简历 ... [详细]
  • 探究大数据环境下Kafka实现高性能的几个关键因素
    在大数据环境下,Kafka能够实现高性能的关键因素在于其独特的设计和优化策略。尽管Kafka的消息存储在磁盘上,这通常被认为会降低性能,但通过高效的文件管理和批量处理机制,Kafka能够在高吞吐量和低延迟之间取得平衡。此外,Kafka还利用了零拷贝技术、压缩算法和异步IO等手段,进一步提升了系统的整体性能。这些技术不仅保证了数据的可靠性和持久性,还使得Kafka成为处理大规模实时数据流的理想选择。 ... [详细]
author-avatar
mobiledu2502853463
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有