Skip to content

RobustMQ 的设计思考:为什么选择组合而非创新

关于创新的疑问

最近有朋友问我:RobustMQ 的突破性创新在哪里?

这个问题让我停下来认真思考了一段时间。老实说,我也不知道 RobustMQ 有什么突破性创新。设计存储层时,用的是 Raft、ISR、RocksDB、分段存储、分层迁移,这些都是业界已有的成熟技术。架构上借鉴了 Kafka 的日志模型、Pulsar 的存算分离、KRaft 的内置元数据服务。没有哪个部分是 RobustMQ 首创的。

一开始我对此有些不安。做开源项目,如果没有技术创新,是不是就没有价值?是不是应该想办法发明点新东西,搞点学术突破?但思考了一段时间后,我想明白了一些事情。

基础设施的特殊性

在基础设施领域,特别是消息队列这种核心组件,用户要的不是"创新",而是稳定、可靠、性能好、成本低。

我问自己:如果我是用户,我会因为一个消息队列"技术创新"而选择它吗?答案是不会。我会看它稳定吗?性能够不够?会不会丢数据?成本高不高?运维复杂不复杂?如果这些都满足,技术是新是旧我不关心。如果这些不满足,技术再创新我也不敢用。

看看业界成功的项目,好像也印证了这个想法。Kafka 不是发明了新技术,而是把消息队列改成了日志模型,这个思路来自数据库的 WAL。Docker 不是发明了容器,Linux 早就有 cgroups 和 namespace,Docker 只是把容器技术包装得好用。Git 不是发明了分布式版本控制,BitKeeper 更早,Git 只是开源且好用。

它们的成功不在于技术突破,而在于解决了真实问题,降低了使用门槛,做得比前辈更好。

组合也需要深入思考

虽然决定不刻意追求创新,但这不意味着简单地把现有技术拼凑起来就行。如何组合,组合什么,这本身需要深入思考。

Kafka 的 ISR 很成熟,Pulsar 的存算分离也很好,但能不能把两者结合起来?Pulsar 做了存算分离,但用的是 Broker + BookKeeper + ZooKeeper 三套系统,运维复杂。能不能用单进程实现存算分离?Kafka KRaft 去掉了 ZooKeeper,但仍然是存算一体。能不能在去掉外部依赖的同时,也实现存算分离?

这些问题不是"创新",而是"如何更好地组合现有技术"。我们的答案是单进程多角色:同一个 Broker 程序,通过 role 配置,可以主要做计算,可以主要做存储,也可以两者兼顾。内部通过 Raft 实现元数据服务,不需要外部协调系统。

这个设计不新,但我反复想了很久。是不是最优解?不知道。但至少在我们能想到的范围内,这是相对合理的选择。可能还有更好的方案,只是我们现在没想到。

解决当前可见的问题

设计时我列出了当前消息队列的一些明显问题,然后寻找解决方案。

Kafka 扩容需要迁移数据,慢且影响性能。我们用分段存储 + 存算分离来解决:不迁移历史数据,新 Segment 自动流向新节点。这个方案不是我们发明的,分段存储 RocketMQ 在用,存算分离 Pulsar 在用,我们只是把它们组合起来应用到这个具体问题上。

Pulsar 的多组件架构运维复杂。我们用单进程多角色来解决。这也不是新技术,很多系统都有角色配置,我们只是把它应用在这里。存储成本高。我们用分层存储,冷数据迁移 S3。这更不是新东西,业界标准做法。

这些都是现有的、可见的问题,也都有现成的解决方案。我们做的只是把这些方案组合起来,让一个系统能解决所有这些问题。

我能想到的极限

回到最初的问题:RobustMQ 有没有突破性创新?没有。需要吗?

我的真实想法是:需要,但确实没想到更好的突破点。我也希望能有一些独创的技术,能在某个方向上做出真正的突破。但想了很久,确实没想到。消息队列这个领域发展了这么多年,基本的技术路线都被探索过了。Raft、Paxos、ISR、Quorum,各种一致性协议都有。本地存储、对象存储、分层存储,各种存储方式都试过。

我认为当前的设计是我们能想到的极限。在不冒技术风险、不做激进尝试的前提下,合理地组合现有技术,尽可能地解决已知问题,适配更多场景。可能还有我们没想到的更好方案,也可能随着技术发展会出现新的可能性,但至少现在,这是我们能做到的。

工程实现的重要性

想明白了不刻意追求创新,接下来的问题是:如何把这些成熟方案真正实现好?

同样是 Raft,实现得好和实现得差,差距可能很大。同样是 ISR,各种故障场景(网络分区、节点崩溃、磁盘故障)下的正确性,需要仔细处理。同样是零拷贝,是真的零拷贝还是只是概念上的,效果完全不同。

Redpanda 用 C++ 重写 Kafka,架构上没什么创新,但工程实现做得好,性能就是比 Kafka 强。这让我意识到:消息队列这个领域,工程实现的质量可能比架构创新更重要。

RobustMQ 选择了 Rust,没有 GC 停顿,内存安全有编译器保证,这些是语言层面的优势。但能否转化为系统层面的优势,取决于代码质量。分布式系统的魔鬼在细节,每个模块的正确性、每个优化的彻底性、每个边界情况的处理,这些细节的累积决定了最终的质量。

方向对了只是第一步,把每个细节都做好,把性能优化到极致,把稳定性打磨到生产级别,这才是真正的挑战。我不知道我们能不能做好,但至少这是值得努力的方向。

一些不确定

这些想法是现阶段的思考,可能不够成熟,也可能有偏差。

不追求创新是对的吗?会不会因为缺乏创新而失去竞争力?组合现有技术是最优策略吗?会不会错过了某些更好的可能性?单进程多角色的设计真的能兼顾简单性和灵活性吗?还是会在实现中发现它的局限?

这些问题现在没有答案,需要在实践中验证。我们会先在 MQTT 场景落地,看看设计是否经得起考验,然后根据实际情况调整。

总结

RobustMQ 走的是组合和优化的路线,不是突破和创新的路线。不是因为我们不想创新,而是确实没想到更好的突破点,同时也认为当前的组合方案是我们能想到的相对合理的选择。

接下来的重点是把设计落地,通过优秀的工程实现来兑现承诺。能不能成功?不知道。但至少方向上,我们想得相对清楚了。


关于 RobustMQ

RobustMQ 是一个用 Rust 编写的高性能消息队列,通过成熟技术的合理组合解决实际问题。我们还在探索和验证中,很多想法可能会随着实践而调整。欢迎关注我们的 GitHub,参与技术讨论。