Trifle:只存答案、不存事件的开源分析库

查看原文 HN 讨论

文章摘要

Trifle 是一个面向开发者的开源时序分析库,核心设计取舍藏在标题里:它聚合嵌套计数器,而不存储原始事件,并且全部数据都写进你已经在用的数据库里。作者说这个项目十年间被重写了两次,如今在他的正职工作中每天追踪约 10 亿个事件。

项目的来历很能说明设计动机。它 2015 年起源于作者自己写的 Rails APM,挂在 ActiveSupport::Notifications 上,来了几个小用户,然后一个大用户的爬虫应用把一切都压垮了。这件事催生了核心想法:把计数器聚合进预先定义好的时间桶,这样一次写入就能同时递增多个桶。那个 APM 后来没什么起色,逐渐淡出。2021 年作者在正职工作中需要分析能力,于是没有采用现成方案,而是把 Trifle 的想法复活成一个更通用的分析库,借用了一些数据仓库的思路。存储层先用 Redis,再用 Postgres,最终落到 MongoDB——这也解释了为什么 Trifle::Stats 自带多个 driver:DSL 保持统一,存储层随需求变化。他们的场景(巨大写入量、少量读取)下,Postgres 读更快但在大写入量下变慢。

嵌套值是整个方案的关键技巧。一次 Trifle::Stats.track 调用可以在一个 key 下同时提交 count、按状态码细分的 status 映射、size、以及 {sum, count} 形式的 duration,一次性为多个时间桶累积出请求数、成功率、状态码分布和耗时。取回时某个小时的桶看起来就是一个嵌套的聚合结果。要注意的是成功率从不被存储,而是用 200 的数量除以总请求数算出来;平均耗时同理,用 sum 除以 count。你给出指标 key、粒度和时间范围,拿回每个时间点上的聚合值,可以直接喂给图表,也可以回答「过去 30 天的平均响应时间」这类问题。

生态由三部分组成:Trifle Stats(一次 API 调用即可埋点的轻量库)、Trifle App(云端或自托管的看板,含告警和定时摘要)、Trifle CLI(终端查询工具,带 MCP server 模式以对接 AI 智能体)。库支持 Ruby、Elixir 和 Go 三种语言,且三者互相兼容——在一种语言里写入,可以在另一种里读取。作者说他之所以写了 Elixir 版本,是因为 Trifle App 是用 Elixir 写的;Go 版本则是为了 CLI。存储侧可以对接 Redis、Postgres、MongoDB、MySQL 或 SQLite。

规模与成本数据颇有说服力:他们如今追踪每天超过 1 亿个后台任务的活动,折算成约 10 亿个事件。作者说在愿意牺牲一些安全性(在 Mongo 里关掉 journaling 和 write concern)的前提下,它跑起来出人意料地便宜——一个三节点的 Hetzner MongoDB 集群,主节点利用率 20%,每月约 1000 美元。

作者也很坦诚地列出了局限:payload 不能装成千上万个 key,否则文档会变得太大、更新效率低下;需要提前做一些规划;以及没有维度(dimensions)的概念——有时你可以把维度嵌套进去(比如国家,总量有限),有时更适合为每个维度值建专门的指标 key(比如客户,会无限增长),而后者会让被追踪的事件数成倍增加,这也正是 1 亿个任务变成 10 亿个事件的原因。许可上,几个库是 MIT,App 是 ELv2 的源码可见许可——可免费自托管,也提供付费的托管云版本。作者说这是他在业余时间做的,没有投资人的钱可以烧在免费服务上。

HN 评论精华