
前些天受邀针对《Pulsar存储计算分离架构设计》做了一次技术分享,下班急急忙忙赶到家,饭也没吃给大家做分享,搞得前面还有点小紧张,不过还好后面越讲越顺了。后面自己回放看自己讲的,整体还算满意吧。分享完后有些观众提了好些个问题交流,在此记录下用户的提的问题并且自己再次总结下以便多年后的回顾。
2.1 Pulsar的读取流程的架构为啥采用三层缓存的设计?

用户是针对这张图的读取Entry时要经过三层缓存,也就是broker cache、writeCache、readCache。
用户提的这个问题真的跟Spring循环依赖三级缓存有点像,就这种问题基本上没人完完全全的答得上来。
(1)broker cache(Broker层缓存)
定位:Broker端的“轻量级缓存”,用于快速响应读请求。
价值:
(2)writeCache(Bookie层写缓存)
定位:Bookie端的“写入缓冲区”,用于批量写入优化。
价值:
(3)readCache(Bookie层读缓存)
定位:Bookie端的“读取缓冲区”,用于缓存热点数据。
价值:
三层缓存的协同逻辑
通过“Broker端轻量缓存+Bookie端写/读缓存”的分层设计,Pulsar实现了读写性能的均衡优化:Broker端快速响应读请求,Bookie端通过批量写+缓存读降低磁盘IO压力,最终保障消息队列的高吞吐、低延迟特性。
2.2 RocksDB需要调优吗?哪些经典的一些场景需要去调整?
RocksDB作为高性能键值存储引擎,虽默认配置已覆盖多数通用场景,但不同业务场景对“性能、资源、可靠性”的优先级存在差异(如高并发写入、低延迟读取、高可用性等),需通过调优适配特定需求。
2.2.1 高并发写入场景(如日志系统、实时数据写入)
2.2.2 低延迟读取场景(如缓存系统、高频查询服务)
2.2.3 高可用性场景(如分布式系统、关键业务存储)
2.2.4 资源受限场景(如嵌入式设备、内存有限环境)
2.2.5 大数据量场景(如PB级数据存储、历史数据归档)
2.3 现在有一股风潮,就是去ZK,Pulsar也有其它的一些元数据管理组件,你是怎么去看待这股风潮的?
用户提的这个问题挺好,早在五年前我就有在思考这个问题,像主流的消息中间件Kafka、RocketMQ、Pulsar都在去ZK。
这里老周提一嘴,像Kafka移除了ZK后,是使用了内部的核心元数据管理组件KRaft,Kafka Broker自身承担元数据管理职责,这不仅仅让运维省心省力,因为不需要再单独部署一套ZK集群了,降本增效。
像RocketMQ的元数据管理由NameServer负责了,核心组件为RouteInfoManager,RocketMQ通过Broker与NameServer的心跳机制实现路由注册,元数据管理聚焦于“路由信息+Broker状态”的高效维护。
Pulsar的话,我在直播内容也有讲,它采用可插拔的元数据管理架构,Pulsar允许用户根据需求选择元数据存储(如RocksDB、本地存储、Etcd、Zookeeper),灵活适配不同业务场景。
那么老周是如何看到这股去ZK风潮的呢?首先你得知道ZK的适用场景,ZK是CAP理论中的CP,是强一致性的。你可以想一想,对于分布式消息引擎来说,优先保障啥?那肯定是AP(可用性)的,一个分布式消息引擎不能因为某个元数据管理组件(ZK)挂了而导致整个消息引擎瘫痪,这个是非常危险的。
还有一个点,ZK在高并发大量元数据写入场景,性能有瓶颈,有可能导致选主异常,造成脑裂的现象,这也是非常危险的。
老周举的这两点场景足以让你去ZK了,但老周更想说的是,好的架构不是一蹴而就的,而是慢慢迭代演讲的。这也说明了为啥很多组件开始就是用的ZK,因为刚开始够用,当自身系统慢慢出现了瓶颈才慢慢换掉的。
2.4 怎么理解Bundle,有没有更通俗的介绍?
当时直播的时候,我感觉我给用户解释的还不够通俗,还是有点专业术语在,这里我重新梳理了下,尝试更通俗的写一下。
你可以先简单理解下,Bundle的“工作逻辑”:分组→分配→动态调整。
2.4.1 Bundle的“身份”:Topic的“分组管理员”
Pulsar的Topic是“消息的收发通道”(比如电商系统里“订单消息”“库存消息”就是不同Topic)。但当Topic数量爆炸式增长(比如百万级)时,Broker要给每个Topic分配“谁负责接收消息、谁负责存储消息”,就会像“给百万个快递员分配包裹”一样混乱。
Bundle就是把Topic“分组打包”,让Broker按“组”分配任务,减少管理压力。
2.4.2 Bundle的“工作逻辑”:分组→分配→动态调整
2.4.2.1 分组:把Topic“打包”成Bundle
Pulsar会把Namespace(命名空间,类似“业务分组”)下的所有Topic,按“哈希算法”分成若干个Bundle。
举个栗子:
假设一个Namespace里有6个Topic(Topic0 ~ Topic5),Pulsar会把它们分成4个Bundle(Bundle0 ~ Bundle3),每个Bundle里装1~2个Topic。
2.4.2.2 分配:Broker“认领”Bundle
Broker(消息服务器)启动后,会主动“认领”Bundle:
2.4.2.3 动态调整:负载不均时“搬家”
如果某个Broker压力太大(比如Broker1要处理的Topic消息量暴增),Pulsar会触发“负载均衡”:
2.4.3 Bundle的“价值”:解决“百万级Topic下的负载难题”
Pulsar的Topic数量可能达到百万级,如果直接让Broker“一个一个管理Topic”,效率会极低。Bundle通过“分组管理”,把“百万个Topic”变成“几十个Bundle”,让Broker按“组”分配任务,既减少了管理压力,又保证了负载均衡。
2.5 跨地域复制同步消息之后,客户端切换集群有没有最佳实践?比如说什么时候开始切换?或者说如何避免减少漏消息或者重复消费?
这个问题老周没有回答的很好,因为切换集群我们有专门的运维来处理,我倒是给用户分享了下如何避免减少漏消息或者重复消费的方案。
2.5.1 切换时机
2.5.1.1 同步完成度验证
2.5.1.2 业务优先级触发
2.5.2 减少漏消息/重复消费:技术手段+流程设计
漏消息与重复消费是跨地域复制的核心痛点,需从“技术保障”与“流程规范”双维度解决:
2.5.2.1 技术层面:依赖平台原生能力
2.5.2.2 流程层面:规范切换操作
2.5.3 总结:切换时机与风险规避的核心逻辑
2.6 BK里面的Qurnumn一致性协议与常见的Raft有啥本质的区别?为啥BK不用Raft?
这个用户问的这个问题也问的很好,这个得从Quorum与Raft的本质区别说起了。
2.6.1 Quorum与Raft的本质区别
2.6.1.1 设计目标
2.6.1.2 实现逻辑
2.6.1.3 适用场景
2.6.2 BK(分布式系统,如分布式存储、数据库)不采用Raft的原因
BK选择Quorum而非Raft,核心是“业务场景匹配度、技术复杂度、性能权衡”的综合考量:
2.7 你前面提到的Oxia项目,对比ZK的话各自的优劣?

Oxia 提供了一种分片架构,旨在高效管理分布式元数据。在云原生应用领域,可扩展性和高可用性至关重要。传统的无分片架构系统虽然在数据一致性方面表现出色,但在处理超大型数据集或高吞吐量场景时往往会面临诸多限制。而这正是 Oxia 的优势所在。Oxia 的优势不就刚好弥补了 ZK 了劣势了呀!
借助 Oxia,您可以获得一个可扩展、稳健且灵活的分布式系统元数据管理解决方案,从而充分发挥现代云原生架构的潜力。
Zookeeper | Oxia | |
|---|---|---|
架构设计 | 采用强一致性+单点主节点架构,数据存储在主节点,副本节点仅用于故障恢复,架构更偏向“集中式强一致性”。 | 采用分布式架构,数据分散存储于多节点,支持水平扩展,适合大规模元数据存储与高并发场景; |
性能表现 | 强一致性机制(如ZAB协议)保障数据强一致性,但写入性能受主节点处理能力限制,高并发写入时性能瓶颈更明显。 | 分布式架构下,写入与读取性能可通过节点扩容线性提升,适合高并发、大规模数据场景; |
扩展性 | 强一致性+单点主节点的架构,扩容需谨慎(主节点切换复杂),扩展性弱于分布式架构。 | 分布式架构天然支持水平扩容(增加节点提升性能),适合业务规模快速扩张的场景; |
生态与场景适配 | 在分布式协调、配置中心、服务注册等场景中生态成熟(如Kafka、Hadoop等广泛集成),强一致性特性更适配“数据一致性优先”的业务场景。 | 作为分布式元数据存储系统,更适配大规模分布式系统(如云原生环境、大数据平台)的元数据管理需求; |
2.8 Pulsar中Bookkeeper磁盘满导致丢消息,这种场景有补救措施推荐吗?有一个订阅一直消费不过来导致磁盘打满,然后没办法去接收这个producer的消息了,生产环境遇到过这种情况。
2.8.1 紧急恢复措施
2.8.1.1 临时扩容
通过pulsar-admin namespaces set-message-ttl设置1秒TTL(仅限紧急情况),强制触发过期数据清理。
bin/pulsar-admin namespaces set-message-ttl <namespace> --messageTTL 1
2.8.1.2 手动清理
定位积压的订阅者,通过pulsar-admin topics重置消费位点或删除旧订阅者释放资源
2.8.2 根本解决方案
2.8.3 存储调优
2.9 ZK主要用来放哪些数据?
2.9.1 元数据存储
2.9.2 运行状态与权限数据
2.9.3 协调同步信息
这次的直播分享有点仓促,下完班饭也没吃赶紧赶回家给大家直播,虽然前面有点紧张,但无伤大雅,因为肚子里长期的积累,无非就是把知道的知识回忆出来给大家分享而已。
老周想说的是,如果你想做一件事,不需要等到万事俱备了才上,准备个七七八八了就可以上,因为等你等到准备的非常完美的时候,机会已经不在了,或者说人家早就赚到盆满钵满了你才入场,汤你都喝不到。
最后老周再说一个点,有些技术你自以为掌握了,但当你写出来发现不知道从何写起;当你写了一篇又一篇的技术博文的时候,但当让你分享给大家听发现你有些逻辑还理不顺。这就是王阳明先生心学中的“知行合一”。
通过这次的直播分享,直播中与大家的互动交流,有些问题也触发到了老周的知识边界,从中我也学习到了很多。感谢自己的这次分享,不仅让技术知识传播给了广大技术人,同时自己也学习到了某些知识边界。
欢迎大家关注我的公众号【老周聊架构】,AI、大数据、云原生、物联网等相关领域的技术知识分享。
欢迎大家添加我的个人微信号,有关AI、大数据、云原生、物联网、消息队列的任何问题都可以问我。