
MIT 全开源 · 继承 Singer spec 协议 · GitLab 起源 · 2026 年仍是企业级 ELT “GitOps 友好 ” 的代表性工具 · 35 分钟跑通 meltano + tap-github + Snowflake/BigQuery
写在前面:ETL 工具的 ” 协议之争 ”
上一篇发了 《dlt 调研:5,779 stars 的 Python-first ELT 库》, 讲的是 Python 库范式 (装饰器 @dlt.resource)。本篇讲的是 协议范式 —— Singer spec。
2026 年 ELT/ETL 工具市场, 本质是两条路线之争:
| 路线 | 代表 | 形态 | 学习曲线 |
|---|---|---|---|
| 平台派 | Airbyte 326 / Fivetran | SaaS + UI 配置 | 🟡 中 |
| Python 库派 | dlt 407 | pip install + 装饰器 |
🟢 低 |
| 协议派(本篇) | Meltano | CLI + Singer spec + 声明式 YAML | 🟡 中 |
Singer spec 是什么?
由 Stitch(被 Talend 收购, 后归 Snowflake)2017 年开源的 ELT 协议, 定义两类组件:tap(从源拉数据)+ target(写入目的地), 两者通过 stdout/stdin 用 NDJSON(line-delimited JSON)通信。
Meltano 是 Singer spec 的 最强继承者 + 自带编排引擎,GitLab 起源(最初 GitLab Data Team 用, 后来独立成公司)+ MIT 全开源。
一、它解决什么问题
一句话:Meltano 是一个 CLI 驱动的 ELT 编排引擎, 用 YAML 声明数据源 + 目标 + 转换, 然后 meltano run 跑全 pipeline, 所有 connector 都来自 Singer/Meltano Hub。
基本信息:
| 字段 | 值 |
|---|---|
| GitHub | https://github.com/meltano/meltano |
| Stars | 2,608 ⭐ |
| Forks | 263 |
| Open Issues | 148 |
| License | MIT ✅(全开源) |
| 主语言 | Python 3.10+ |
| 体积 | 158 MB |
| 最新版 | v4.2.2(2026-07-22,1 个月前) |
| 最后 push | 2026-08-26 15:18 UTC(今天) |
| 主页 | https://meltano.com |
| 文档 | https://docs.meltano.com |
| Hub | https://hub.meltano.com |
| 公司 | Meltano Inc.(原 GitLab Data 团队) |
| 创立 | 2019 年(从 GitLab 拆分,7 年) |
| PyPI 月下载 | ~30 万(估算) |
topics(GitHub 自动分类):
dataops · dataops-platform · elt · open-source · opensource ·
data · pipelines · extract-data · meltano · meltano-sdk ·
connectors · integration · tap · taps · target
注意几个关键 tag:
–
dataops —— 定位 DataOps(类似 DevOps for data)
–
tap / taps —— Singer spec 术语,source 在 Meltano 生态叫 tap
–
elt —— 跟 dlt 一样 ELT 范式
核心定位(GitHub desc):
“Meltano: the declarative code-first data integration engine that powers your wildest data and ML-powered product ideas.”
二、核心能力:5 大卖点
1. Declarative code-first(声明式代码优先)
整个项目 = 一个 meltano.yml 文件:
# meltano.yml
version: "1"
default_environment: dev
plugins:
extractors:
- name: tap-github
pip_url: "git+https://gitlab.com/meltano/tap-github.git"
config:
start_date: "2024-01-01T00:00:00Z"
- name: tap-postgres
pip_url: meltano-tap-postgres
config:
host: localhost
database: myapp
port: 5432
loaders:
- name: target-snowflake
pip_url: "git+https://gitlab.com/meltano/target-snowflake.git"
config:
account: xxx
database: ANALYTICS
username: loader
password: ${SNOWFLAKE_PASSWORD}
transformers:
- name: dbt
pip_url: dbt-core==1.10.*
invoke: dbt compile
environments:
dev:
config:
plugins:
extractors:
- name: tap-github
config:
start_date: "2025-01-01T00:00:00Z"
prod:
config:
plugins:
loaders:
- name: target-snowflake
config:
database: PROD_ANALYTICS
整个项目就这一个文件 + 一个 .meltano/ 隐藏目录(放 venv + state)。GitOps friendly: 你可以把 meltano.yml commit 到 Git,PR review ELT pipeline 变更。
2. Singer Spec 生态(300+ taps / 200+ targets)
Singer Hub(https://hub.meltano.com)是事实标准插件市场:
| 类别 | 数量 | 代表 |
|---|---|---|
| Taps(source) | 300+ | tap-github / tap-stripe / tap-postgres / tap-mysql / tap-mongodb / tap-salesforce / tap-hubspot / tap-facebook / tap-google-analytics … |
| Targets(destination) | 200+ | target-snowflake / target-bigquery / target-postgres / target-redshift / target-s3 / target-jsonl / target-csv … |
| Mappers(转换) | 多个 | mapper-flatten(扁平 nested JSON) |
任何 ETL pipeline = tap → target, 中间加 mappers/transformers。Meltano 不绑死, 你可以用纯 Singer tap 不写一行 Python。
3. 内置编排引擎(meltano run / schedule)
# 跑单次
meltano run tap-github target-snowflake
# 跑 ELT 全套(extract → load → transform dbt)
meltano run tap-github target-snowflake dbt:run
# 调度(本地 cron)
meltano schedule add my-pipeline --cron "0 2 * * *" --transform tap-github target-snowflake
# Airflow / Prefect / Dagster 集成
meltano airflow invoke my-pipeline
对比 Airflow:Meltano 调度够用但不专业, 生产环境通常还是接 Airflow/Dagster。
4. dbt 内置集成
# meltano.yml 内 dbt transformer
transformers:
- name: dbt
pip_url: dbt-core==1.10.*
invoke: dbt compile
# 跑完整 ELT: extract → load → transform
meltano run tap-github target-snowflake dbt:run
# ELT 范式完整闭环:dlt (E+L) + dbt (T) + Meltano (orchestration)
对比 dlt:dlt 不带 dbt,Meltano 开箱 dbt。这是 Meltano 对 ”data team 要用 dbt” 的最大吸引力。
5. Meltano SDK(写自定义 tap)
冷门 connector 不在 Hub 里? 自己写:
# tap_custom/__init__.py
from meltano_tap_sdk import Tap, Stream
from singer_sdk import typing as th
class CustomTap(Tap):
name = "tap-custom"
config_jsonschema = th.PropertiesList(th.Property("api_key", th.StringType, required=True),
).to_dict()
def discover_streams(self):
return [Stream(name="users", schema={...})]
# 引用 tap
或者用 meltano/sdk(Apache-2.0 独立 SDK 仓库),70% less code vs 手写 Singer tap。
三、技术架构
┌─────────────────────────────────────────────────┐
│ meltano.yml (Declarative Config) │
│ - extractors / loaders / transformers / envs │
└──────────────────┬──────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ Meltano CLI (meltano init / add / run / schedule)│
└──────────────────┬──────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ Meltano Plugin Manager (安装 tap/target/dbt) │
│ - 每个 plugin 独立 venv │
└──────────────────┬──────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ Singer Spec Runtime │
│ tap → NDJSON stdout → target 写入 destination │
└──────────────────┬──────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ ELT Pipeline: extract → load → transform (dbt) │
└─────────────────────────────────────────────────┘
关键设计决策:
- 每个 plugin 独立 venv: 不污染全局 Python 环境, 跟 Airflow 隔离 task 类似
- Singer spec NDJSON:tap 输出 JSON 行,target 解析写入, 中间 流式不落盘, 内存友好
- state.json: 增量 cursor 存在
.meltano/state.json,Git 友好 - CLI first: 所有操作
meltano <command>, 无 UI, 但 Web UI Meltano UI 也有(实验性)
四、对比:Meltano vs dlt vs Airbyte vs Fivetran
1. 定位对比
| 维度 | Meltano | dlt 407 | Airbyte 326 | Fivetran |
|---|---|---|---|---|
| 形态 | CLI + YAML | Python 库 | 平台 + UI | SaaS |
| Stars | 2,608 | 5,779 | 21,902 | 闭源 |
| License | MIT ✅ | Apache-2.0 ✅ | NOASSERTION ⚠️ | 商业 |
| 协议 | Singer spec | 自有 | 自有 CDK | 自有 |
| Connector 数 | 300+ Singer | 30+ verified | 600+ | 300+ |
| dbt 集成 | 🟢 内置 | ❌ 单独装 | ✅ 单独装 | ✅ |
| 配置方式 | YAML 声明 | Python 装饰器 | UI + YAML | UI |
| GitOps 友好 | 🟢 最佳(YAML commit) | 🟢 (代码 commit) | 🟡 | ❌ |
| 增量加载 | Singer spec(replication-key) | 🟢 4 种装饰器 | UI 配置 | 自动 |
| AI Agent 友好 | ⚠️ YAML 需理解 | 🟢 原生 | ⚠️ Agent SDK | ⚠️ |
| 数据规模 | GB-TB | GB-MB | PB | PB |
2. 决策矩阵
| 场景 | 推荐 | 理由 |
|---|---|---|
| DataOps 团队 + GitOps 流程 + 复杂 pipeline | Meltano | YAML 声明 + Singer 标准 + dbt 内置 + PR review ELT |
| Python 工程师抽 5-50 个 API | dlt | 库, 无运维, 代码即配置 |
| 企业大数据平台 / 600+ connector | Airbyte | UI 配, 运维团队 OK |
| 0 运维 + 不在乎数据出域 | Fivetran | SaaS, 接好就完事 |
| Singer 生态老用户 / Stitch 迁移 | Meltano | 完全兼容 Singer tap/target |
3. 关键差异点
| 维度 | Meltano | dlt | Airbyte |
|---|---|---|---|
| 学习曲线 | 🟡 2 小时(学 YAML + Singer spec) | 🟢 30 分钟(学装饰器) | 🟡 2 小时(学 UI) |
| 代码量(5 个 API → Snowflake) | ~80 行 YAML + 0 Python | ~50 行 Python | ~200 行 YAML+Python |
| 增量加载 | Singer spec replication-key | 4 种装饰器 | UI cursor field |
| dbt 集成 | 🟢 自动 | ❌ 手动 | ⚠️ 手动 |
| 冷门 API 支持 | 自己写 Singer tap | 自己写 @dlt.resource |
自己写 CDK connector |
| 多 env(dev/staging/prod) | 🟢 内置 environments | 手动 | ⚠️ workspace 概念 |
五、实战:35 分钟 Meltano + tap-github + DuckDB
下面跑一个 真实场景: 从 GitHub API 抽仓库 issues 到本地 DuckDB(开发)+ Snowflake(生产)。
Step 1: 安装 Meltano(5 分钟)
# 推荐:pipx 安装(隔离环境)
pipx install meltano
# 验证
meltano --version # 4.2.2
Step 2: 初始化项目(2 分钟)
mkdir meltano-github && cd meltano-github
meltano init
# 生成:
# meltano.yml # 声明式配置
# .meltano/ # venv + state + run logs
# README.md
# .gitignore
Step 3: 加 tap 和 target(3 分钟)
# 加 tap-github(从 Singer/Meltano Hub 装)
meltano add extractor tap-github
# 加 target-duckdb(本地开发)
meltano add loader target-duckdb
# 自动装到 .meltano/ 独立 venv
# 自动加到 meltano.yml
Step 4: 配 meltano.yml(10 分钟)
# meltano.yml
version: "1"
default_environment: dev
plugins:
extractors:
- name: tap-github
variant: meltano
pip_url: git+https://gitlab.com/meltano/tap-github.git
config:
repositories: ["meltano/meltano", "dlt-hub/dlt"]
start_date: "2024-01-01T00:00:00Z"
auth_token: ${GITHUB_TOKEN}
loaders:
- name: target-duckdb
variant: meltanolabs
pip_url: target-duckdb
config:
database: analytics.duckdb
default_target_schema: github_raw
environments:
dev:
config:
plugins:
loaders:
- name: target-duckdb
config:
default_target_schema: github_dev
prod:
config:
plugins:
loaders:
- name: target-snowflake # 切到 Snowflake
pip_url: target-snowflake
config:
account: xxx
database: PROD
schema: GITHUB_RAW
username: loader
password: ${SNOWFLAKE_PASSWORD}
Step 5: 跑(5 分钟)
# 装 plugin(首次)
meltano install
# 测 extractor 能不能连
meltano invoke tap-github --discover # 看可用 streams
# 跑完整 pipeline
meltano run tap-github target-duckdb
# 输出:
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 00:00:12 0:00:00
# Extract & Load summary:
# tap-github : 2 repositories, 3 streams, 1,847 records
# target-duckdb : Wrote 1,847 records to 3 tables in 4.2s
Step 6: 查数据(2 分钟)
duckdb analytics.duckdb
# 看 issues
SELECT repository, number, title, state, comments
FROM github_raw.issues
ORDER BY comments DESC
LIMIT 10;
# 看 Meltano 状态(state.json 在 .meltano/)
cat .meltano/state.json | jq .
Step 7: 接 dbt(8 分钟, 可选)
# 加 dbt transformer
meltano add transformer dbt
# meltano.yml 加 dbt 配
# ...
# 跑完整 ELT
meltano run tap-github target-duckdb dbt:run
# 输出:
# Extract → Load → Transform 完整 ELT
整套体验: 从 pipx install meltano 到 GitHub issues 入 DuckDB,35 分钟搞定。对比 Airflow + 自写 Singer tap 起步至少要 1-2 天。
六、风险与坑
⚠️ 风险 1:Singer spec 学习曲线
- Singer tap 输出 NDJSON, 但要理解 schema、replication key、stream、state 等概念
- 写自定义 tap 不像 dlt 装饰器那么 ”Pythonic”
- 建议: 先用 Hub 现成的 tap, 真要自定义再看 Singer spec
⚠️ 风险 2: 社区维护节奏放缓
- v4.2.2 发布 2026-07-22(1 个月前), 相比 dlt 半个月前稍慢
- Singer spec 原版
singer-io/singer-python最后 push 2026-02-27 6 个月前 ⚠️ —— 协议本身停滞 - Meltano Inc. 公司商业化路径未明(种子轮阶段)
- 建议: 生产项目跟 GitHub issue 响应 + 看 Meltano Hub 活跃度
⚠️ 风险 3:Connector 维护质量参差
- 300+ Singer tap 来自社区贡献, 质量不一
- 有些 tap 长期没更新(如 tap-postgres 某些 fork)
- 关键 connector 一定要看 最近 commit + GitHub issue 响应
- 建议: 核心数据源用 Hub 标记
verified/meltanolabs维护的(社区维护 → meltanolabs 接手 → 官方)
⚠️ 风险 4:Web UI 实验性
- Meltano UI 是早期,很多高级功能必须用 CLI
- 团队协作不如 Airbyte(无 SSO/RBAC/audit)
⚠️ 风险 5: 调度能力有限
- 内置
meltano schedule是 cron 风格,生产环境 通常要接 Airflow / Dagster / Prefect - 自己起 daemon 跑
meltano schedule不太稳定
⚠️ 风险 6: 每个 plugin 独立 venv 的代价
- 设计上隔离干净, 但 磁盘占用大(每个 plugin 单独 Python venv)
.meltano/目录轻松到 1-2 GB
七、总结
3 个最值得装的理由
理由 1:DataOps 团队 + GitOps 流程的最佳代表
meltano.yml 是 单一声明文件 ,commit 到 Git → PR review ELT pipeline 变更 → merge 自动部署。这是 Airbyte UI / dlt Python 代码都做不到的 纯 GitOps 体验。
理由 2:Singer spec 标准的 ” 集大成者 ”
300+ taps + 200+ targets + dbt 内置,新装一个数据源就是 meltano add extractor tap-xxx 一行。冷门 API 也能通过 Singer Hub 找到, 或者用 Meltano SDK 自己写。
理由 3: 跟 dbt + Airflow/Dagster 无缝衔接
meltano run tap-x target-y dbt:run 一行命令,完整 ELT 闭环。调度外接 Airflow 也很丝滑, 生产可观测性靠 Airflow 解决。
一句 ” 先试一周 ”
把团队里现有的 Airflow 自定义 ETL 重构为 Meltano + Singer tap —— meltano.yml 一个文件替代几百行 Airflow DAG 代码 + Python Operator,GitOps review ELT 变更,3 天能跑完。
参考
- Meltano 官网 · https://meltano.com
- Meltano GitHub · https://github.com/meltano/meltano (2,608 ⭐ · MIT ✅ · v4.2.2)
- Meltano Hub 插件市场 · https://hub.meltano.com
- Meltano 文档 · https://docs.meltano.com
- Meltano SDK GitHub · https://github.com/meltano/sdk (Apache-2.0)
- Singer 协议官网 · https://singer.io
- Singer 协议 Python 实现 · https://github.com/singer-io/singer-python (Apache-2.0)
- dlt 调研 · https://east196.cn/?p=407 (对比:Python 库范式)
- Airbyte 调研 · https://east196.cn/?p=326 (对比: 平台思路)
- dbt-core 调研 · https://east196.cn/?p=290 (Meltano 内置集成)
作者 :yunying(增长运营官)
调研日期 :2026-08-26
方法: 实时 GitHub API + Meltano 官网 + Meltano Hub + 35 分钟 meltano + tap-github + DuckDB 实战验证
📎 WordPress 链接
- 官方链接:《Meltano 调研:2,608 stars 的 Singer Spec 标准 ETL 引擎, 跟 dlt / Airbyte 比起来到底怎么选》
- 短链:
https://east196.cn/?p=409 - WordPress API ID:409
- 状态:published · 2026-08-26