背景介绍
我们公司有一个 BI 系统,用的是 FineBI。为了避免订阅费,用的是个人版——除了会限制并发和一些用不到的功能,其他还好。数据计算 / 清洗用的是腾讯云的 MapReduce,数据同步到clickhouse 中。
搭建系统的人早已离职,目前这个系统经常会出现问题,特别是腾讯云的 MapReduce,不知道为什么总是 OOM 爆内存,导致数据无法定时同步。
运营经常找我让我去修一下,搞得我很烦——因为我也不知道从哪里入手。但是看数据又是刚需:虽说是个小公司,但也是一个有相当多注册用户的 C 端 App,数据库里有几十亿条记录,直接用 SQL 统计,很可能就把线上服务搞崩了。
问题拆解
问题出在哪
MapReduce 内存泄露。我让 AI 读日志,分析结论就一句话:加内存。
这就很尴尬了——本来每个月要专门给 MapReduce 支付 8000 多的费用,再加内存又是几千块支出。对本来财务紧张到要开除保洁阿姨的小公司来说,这可能就是压在骆驼身上的最后一根稻草。
第一步:重构数据仓库
与其继续给 MapReduce 续命,不如从根上把数据仓库重构了。经过一番 AI 互动,决定采用 Doris + Flink CDC 的方案。
相比原本沉重的 Hadoop 生态,组件精简到只有 2 个,还带来 2 个史诗级优势:
- 数据可以做到半实时同步:运营人员不用等到第二天才能看到销售情况和活跃数据,Flink CDC 可以实现相对准时的数据同步;
- Doris 的 JOIN 效率极高:原本留存的大量定时更新的 backfill 脚本,都可以不用管了。
第二步:BI 工具的去留
数据仓库定了,下一个问题是:还要不要继续用 FineBI?
- 个人版走不下去:目前用的版本非常旧,而且 FineBI 个人版并非云原生,需要把所有组件都放在一个镜像中才能运行。如此沉重的镜像在集群中运行,本身就是严重的隐患——继续用,不过是又埋了一个坑。
- 企业版用不起:去了解了一下,一年十万订阅费——告辞!
- 开源也接不住:Metabase / Rill / Evidence 都看过,并真实部署调研过。但要把 FineBI 的图表迁移过去,首先需要一个非常懂之前这些看板是怎么搭建的人,梳理数据的因果关系,再熟练使用新平台重新搭建。 非常凑巧的是(并非凑巧),FineBI 上搭建看板的同事也离职了。这活让我干?我可不想干!
摆在桌面上的三个方案
- 升级 FineBI 企业版:支付一年十万订阅费,把数据底层从 ClickHouse 改成 Doris,再迁移数据源——工作量和重建看板没有区别。除非重建 Hadoop 体系,但这玩意我感觉我搞不定:十来个组件、各种自定义脚本在里面跑,Hadoop 生态本身也没有针对云原生设计,搭建起来不一定比重建看板简单(后面部署 doris和 flink-cdc 也证明了,hadoop生态云原生化坑挺多的)
- 用开源方案 Metabase:在调研的 3 个开源项目中算比较成熟的,但需要专门招聘一个数据处理的同事来研究怎么迁移。迁移时间和最终成本并不会少多少。
- 自己做一个 BI-Agent:让 AI 来完成数据迁移,同时让搭建看板的学习成本降低为 0。
方向确定
经过前面的问题拆解,对于我们这个小公司,唯一可行的解决方案就是 3。如果采用 1 / 2,基本就是往干倒闭的节奏。
而且选择方案 3,也是我经过深思熟虑后最简单的解决方案。在写本文的时候,我总共用了 7 天时间完成整个系统的实现并上线。虽说还不完美,但已经可以完全替代现有的 FineBI。又是把公司从存亡危急中拯救的一天(笑死)。
架构设计
前面数据仓库的设计已经明确了,采用 Doris 和 Flink CDC。
整个系统的实现代码采用 Rust——因为 Rust 编译之后就是一个小巧的二进制,镜像极小,内存泄露困难,计算效率极高。除了难写,针对目前的需求场景是完美的语言。难写也是 AI 写(哈哈哈)。
架构设计图如下:
介绍一下各组件的功能:
- portal:门户入口,整个系统对外提供服务的 Web 页面;
- bi-agent:用来创建 / 修改看板,内嵌一个 LLM 服务,在约束下进行看板的编辑和修改;
- bi-checker:检查 agent 产出的看板的代码质量,如果检查不合格,打回去让 AI 重写——因为看板就是 React 代码,可以用成熟的工具进行代码质量检查;
- dashboard-app:看板运行时,bi-agent 写的看板就在这上面运行,是一个独立的服务,可以被嵌入到任意的网页中;
- bi-data-layer:安全代理,审核访问人的权限,约束 SQL 格式避免注入攻击;
- bi-etl:并不负责数据抽取,就是做一些建表、物化之类的杂活。
开发日记
第一天
- 纯调研和设计框架,明确技术难题和如何解决。
第二天
- 先让 AI 搭建开发环境,可以自行测试调试;然后让 AI 根据框架设计开工,完成初稿。
第三天
- 本地测试通过,修复各种 BUG。
第四天
- Flink CDC 和 Doris 上线,进行数据抽取。
- 众所周知,小公司的数据不会那么规范——什么中文字段名、复合字段等等,Flink CDC 连续宕机。
- 特别搞笑的是,我司数据库的自增字段,flink cdc 居然无法同步,也不知道是不是经常直接用ID增加数据的原因(苦笑
- AI 自己居然可以写 patch 注入来解决,只能说 AI 很牛逼。
第五天
- 数据同步还有问题?
- 我看着带了 5 个 patch 的 Flink CDC 陷入沉思,决定并行做 2 条路:
- 一条是让 AI 自己用 Go 实现一个精简版的 Flink CDC;
- 一条是让 AI 把 Flink CDC 源码改了,重新打包。
- 最后,弱智的 AI 浪费了我大量 token,抄了一个满是 bug 的 Go 版本 Flink CDC;走改源码的那条正常工作了,问题终于得到解决。
第六天
- 迁移 FineBI 看板:让 AI 根据 FineBI 的备份数据生成一个转换脚本,生成当前项目的看板代码。
- 一整天都在解决 bug,把一些用不上的看板删了。这天最终可以正常展示了——虽然有点难看,但是数据是通的。
- 其实到这一天已经可以交付了,运营可以看这边的数据了。
第七天
- 开始调教 agent,增加一些工具。
- 优化看板编写的准确性,精简提示词。
- 优化 RAG 表格语义召回。
- 继续修BUG
以上开发日志只记录了我觉得还比较重要的事情,实际上忽略了很多细节工作,比如权限管理、物化表管理、看板的版本管理。
而且项目我认为并不算开发完成,还有很多可以优化以及还没实现的地方。我做了可迭代的设计,让 AI 可以快速定位问题、梳理原因(应该会再写一篇博客)。
项目特点
- 没有任何数据库:整个项目的配置通过 GitOps 的方式部署,非常方便迁移 + 扩容,非常的云原生,对 AI 极其友好,不会让问题隐藏在不可见的地方。如果非要说有数据库,那就是 doris 数仓。
- 看板即代码:看板是 React 代码,自然保存在 Git 仓库中。bi-agent 会创建一个 worktree 来进行编辑,编辑完成后自动推送到 Git 仓库保存。你可以选择本地编辑看板文件并推送,也可以选择用当前项目的 agent 来编辑代码——最终上线只需要一个 PR 合并的步骤。
- 表格语义文件化管理:表格语义也是文件形式,被 Git 管理。这个我专门做了下,可以在界面中进行编辑,免得运营人员去拉代码。底层走的也是看板代码管理的逻辑,改完之后需要通过 PR 合并到主分支。
结语
后面我会再水一些章节,那些章节我会用 AI 把项目框架的细节描述一下。很多精彩的设计——比如看板的版本迭代、零配置等——都会在这些文章中具体呈现。
本文纯手写,中间一张架构图是我让 AI 根据代码画的,其他配图我也懒得配,因为具体数据打码太麻烦了。如果发现文本看得不舒服、想到哪写到哪、写得和流水账一样、还有很多错别字——你的感觉是对的。