Flink
收录于 工程治理体系
Flink 和 Go 之间,我最后为什么没继续自研引擎
这次纠结表面上像 Flink 和 Go 的技术选型,最后把两条路拉开的不是执行效率,而是多租户场景下的成本结构、平台复杂度,以及 AI 时代的交付成本。
在 《ClickHouse 变成系统风险以后,别再把它当性能优化题》 那篇里,我写的是,为什么在本地化场景里,我开始把原来压在 ClickHouse 那条路径上的一部分业务逻辑往 Flink 挪。那一步当时还谈不上一套完整方案,更像是先落地、先证明价值的第一步。
但只要这一步真的走起来,后面的题就会自然冒出来:如果这类能力还要继续长,我们到底是继续沿着 Flink 往下收,还是应该往更独立的资产中台、通用引擎去做?
这篇文章讨论的,其实就是那之后的业务演进。
这件事一开始看起来很像一道标准技术选型题。摆在面前的问题也很直接:继续用 Flink,还是用 Go 自己做一套更轻的引擎?
我最早也是顺着这个方向在想。Flink 的确不轻,资源占用高,运维也复杂。如果只看执行层,很容易得出一个结论:既然我们想要的是更轻、更可控,那是不是该把运行时收回来,自己做。
不过后来一路往下拆,我发现真正卡住我的其实是另一件事:我们说的“降本增效”,到底在降什么成本。执行效率反而排不到最前面。
一开始看上去是技术选型,先爆出来的却是规模
我们的上游是一个很典型的多租户结构。
- 大约 3000 个租户。
- 当前大概是 30 个租户一个 Flink 集群。
算下来,就是接近 100 个 Flink 集群。
如果我们后来做这套引擎,还是照着这个思路往下走,那很可能只是把原来那套体系再复制一遍。上游一百个集群,我们这里再来一百个集群。到这一步,其实问题已经不太像“某个框架重不重”了,而是成本结构本身已经不太能接受。
一百个集群。想想就头疼。
我后面不太愿意把这件事理解成“Flink 要不要换成 Go”。因为在那个阶段,最大的风险根本不在实现语言,也不在算子性能,而在于系统是不是还在沿着一条线性扩张的路继续长。
先要动的,不是框架,而是资源使用方式
我们后来先做的,也跳过了 Flink 还是 Go 的争论,先改资源怎么被使用。
原来的思路更像是每一层都各自消费、各自计算、各自占资源。谁要能力,谁就自己拉一套处理链路。这样做前期很顺手,局部看也不一定有错,但租户数一上来,资源会跟着层层复制。
我们后面改成了另一种方式:上游 Flink 把结果打到平台侧 topic,我们在平台侧统一消费,再往下承接自己的能力。
这一步看起来不像“技术升级”,但它解决的是更靠前的问题。
- 集群数量不再线性增长。
- 上游已经付过的那部分处理成本,可以开始被复用。
- 架构开始从多套独立系统,收敛成一套可复用的平台能力。
回头看,这一步才是这件事里降本最明显的地方。
结构收住以后,再问要不要自己做引擎,答案就没那么简单了
在平台化复用之前,讨论 Go 其实很容易带着一种直觉:Flink 太重了,自己做一个轻量引擎,也许能把资源和运行时都压下来。
但当资源复用、集群规模和架构收敛这些问题先被解决掉以后,原来那个“换掉 Flink 就能降本”的想法开始站不住了。
因为这时候系统最贵的地方已经不是 Flink 本身了。
如果还继续往下做一个 Go 引擎,我们得到的当然不是零:
- 执行层可能会更轻。
- 某些逻辑会更可控。
- 运行时边界也许会更适合自己的业务。
可问题在于,为了拿到这些收益,我们要重新承担的东西太多了,而且很多还不是“写完代码就结束”的一次性投入。
用 Go 自己做,拿回来的不只是执行权,还有整套平台复杂度
表面上看,这像是在做一个轻量引擎;真落到工程里,你会发现自己接手的其实是一整套流处理平台能力。
至少这些东西都跑不掉:
- 状态管理
- 容错和恢复
- 数据重放
- 调度与资源治理
- backpressure 处理
- 可观测性和排障能力
这些能力放在 Flink 里时,你会觉得它“重”。可一旦你决定自己做,它们不会消失,只是从框架外部搬进你的系统内部。
代价也会跟着一起搬进来:
- Debug 更难,因为问题不再有成熟框架帮你兜底。
- 系统会更脆,因为很多边界要靠自己补。
- 对人会更依赖,因为排障、扩展和演进都要建立在自研运行时之上。
后来我对这件事的理解变了。关键在于,你要不要为了局部执行效率,把一整套平台复杂度收进来自己长期背着。
要算的,不只是资源账,还有人效账
如果只盯着 CPU、内存、机器规格这些显性成本,Go 方案很容易显得更有吸引力。
但做到后面我更在意另一笔账:从需求到落地,到长期维护,这条链路到底贵不贵。
这也是我这次重新理解“降本增效”的地方。很多优化从资源视角看没错,从整体视角看却不一定成立。因为成本至少有三层:
- 资源成本,比如 CPU、内存、IO。
- 复杂度成本,比如系统数、链路数、实现数越来越多。
- 人效成本,比如开发效率、维护成本、出错概率和交付速度。
前两年我们更本能地盯第一层,现在我对后两层更警惕。因为资源账通常还能量化,复杂度和人效一旦持续抬高,往往是后面最难慢慢还清的债。
AI 时代以后,成熟框架的价值反而更大了
这次还有一个让我更倾向继续用 Flink 的原因,是我明显感受到 AI 正在改变工程交付方式。
以前我们看框架,更多会看它跑得重不重、生态齐不齐、团队熟不熟。现在我还会多看一层:它是不是足够成熟、标准化、语义清晰,能不能把需求更稳定地翻译成实现。
像 Flink 这类成熟框架,在这件事上反而更占优势。
- 表达方式更标准。
- 生态和经验更完整。
- 很多能力不需要重新定义。
如果某些策略最后能落到 FlinkSQL 上,甚至可以把现有的 SQL 能力继续往下复用,而不是再为一套自研引擎重新发明表达方式。
这件事放在 AI 时代尤其明显。框架越成熟,语义越稳定,后面的生成、补全、排障和协作成本通常就越低。换句话说,成熟框架不只是运行时资产,很多时候也是交付资产。
所以最后没选 Go,不是因为它不行,而是因为现在不值
我最后没有继续往 Go 自研引擎这条路走,不是因为 Go 不好,也不是因为 Flink 天生就更先进。
在我们当时那个阶段里,最大的成本问题已经通过架构收敛先解决掉了。再继续投入一大笔研发和长期维护成本,去优化一个已经不是主要矛盾的点,这件事不划算。
它当然可能在别的阶段成立。比如资源瓶颈真的长期卡在执行层,或者成熟框架已经明显限制业务表达,再或者团队就是要把运行时能力变成核心资产,那自研就有了另外一层意义。
但至少在我们当时那个上下文里,更合理的做法是先把成熟能力吃透,把最影响成本结构的地方改掉,没必要重复造轮子。
我现在怎么理解“降本增效”
这次最有价值的收获,跟“Flink 比 Go 更好”没多大关系——我后来不太愿意再把“降本增效”只理解成机器账了。
很多时候,先该降的,其实是系统里那些线性扩张、重复建设和长期维护的成本,某个组件的资源消耗反而排后面。执行效率当然重要,但它不是每一次都排在最前面的矛盾。
所以如果现在再让我用一句话总结这件事,我更愿意这么说:
先解决结构问题,再优化执行细节。成熟能力能复用就先复用,没必要急着把复杂度收回自己手里。