作者: MoonCake TV 技术团队 (就我自己)
性能提升: 🚀 17 倍加速 (11.5 小时 → 40 分钟)
简单点,说人话,就是我以前的数据处理流程,没有规划,有什么用什么;核心还是太烂了;现在经过和 ai 的多轮对话,终于有了改进
在优化之前,我们的数据处理流程存在以下严重问题:
旧架构数据流:
Source APIs (数据源)
↓
Temporal Workers (数据抓取)
↓ HTTP POST /cf-workers/upsert-batch
Cloudflare Workers (中间层) ← 瓶颈 1: 网络延迟
↓ 写入 D1 数据库
Cloudflare D1 (SQLite) ← 瓶颈 2: D1 性能限制
↓ GET /cf-workers/search-todos-*
meilisearch-sync Worker ← 瓶颈 3: 额外的同步层
↓ POST to meili-search-service
meili-search-service Meilisearch
↓
Cloudflare Workers
↓
用户查询
关键瓶颈:
m3u8_urls
字段需要多次 stringify/parse我们采用了单向数据流的设计理念,彻底简化了数据处理架构:
新架构数据流:
Source APIs (数据源)
↓
Temporal Workers (数据抓取 + 解析)
↓ HTTP POST /v1/upsert-batch (JWT 认证)
meili-search-service PostgreSQL ---> Meilisearch Server (同一个服务器内部)
↓
Cloudflare Workers
↓
用户查询 (通过 m3u8-s1 代理)
之前:
现在:
收益:
之前:
is_indexed
标志位现在:
收益:
之前 (Cloudflare D1):
// m3u8_urls 存储为 TEXT
m3u8_urls: JSON.stringify(item.m3u8_urls); // 需要序列化
现在 (PostgreSQL):
// m3u8_urls 存储为 JSONB
m3u8_urls: item.m3u8_urls; // 直接传递对象,无需序列化
收益:
新的 PostgreSQL Upsert 逻辑:
INSERT INTO table_name (
id, field1, field2, field3, ...
) VALUES ($1, $2, $3, $4, ...)
ON CONFLICT (unique_key1, unique_key2)
DO UPDATE SET
m3u8_urls = EXCLUDED.m3u8_urls,
updated_at = EXCLUDED.updated_at
关键优化点:
ON CONFLICT
实现 upsert (插入或更新)指标 | 旧架构 | 新架构 | 提升比例 |
---|---|---|---|
总处理时间 | 11.5 小时 | 40 分钟 | 17.25x |
网络往返次数 | 4+ 次 | 1 次 | 4x 减少 |
服务层级 | 4 层 | 2 层 | 2x 简化 |
数据库数量 | 3 个 | 1 个 | 3x 精简 |
维度 | 旧架构 | 新架构 |
---|---|---|
数据源 | Cloudflare D1 + PostgreSQL | PostgreSQL 单一数据源 |
中间服务 | Cloudflare Workers + meilisearch-sync | 无 |
数据流向 | 循环依赖 | 单向流动 |
维护成本 | 高(多个服务) | 低(精简架构) |
** 表结构:**
CREATE TABLE IF NOT EXISTS dazahui (
id SERIAL PRIMARY KEY,
mc_id VARCHAR(50) UNIQUE NOT NULL,
title TEXT NOT NULL,
m3u8_urls JSONB, -- 关键:使用 JSONB 类型
.......
CONSTRAINT unique_xxx UNIQUE(xxx, xxxx)
);
旧代码 (写入 Cloudflare Workers):
await fetch("https://cf-workers/upsert-batch", {
method: "POST",
body: JSON.stringify({
items: items.map((item) => ({
...item,
m3u8_urls: JSON.stringify(item.m3u8_urls), // 需要序列化
})),
}),
});
新代码 (直接写入 meili-search-service):
await fetch(`/v1/upsert-batch`, {
method: "POST",
body: JSON.stringify({
items, // m3u8_urls 保持对象格式,无需序列化
}),
});
关键改进:
数据写入 API (JWT 保护):
POST /v1/upsert-batch
Authorization: Bearer <MEILI_INTERNAL_JWT_SECRET>
Request:
{
"items": [
{
"title": "电影标题",
"m3u8_urls": {"第 1 集": "url1", "第 2 集": "url2"},
"language": "zh",
...
}
]
}
Response:
{
"code": 200,
"message": "Batch upsert completed",
"data": {
"processed": 150,
"failed": 0
}
}
ON CONFLICT
实现 upsert 批量操作虽然数据写入性能已大幅提升,但仍有进一步优化空间:
添加查询 API 到 meili-search-service
GET /v1/search-sql?keyword=xxx
(SQL LIKE 搜索)GET /v1/random?limit=20
(随机内容)GET /v1/mc_item/:mc_id
(获取单个内容)更新 m3u8-s1 为纯代理层
/boss/*
路由/v1/*
端点改为代理到 meili-search-serviceMeilisearch 自动索引
核心技术:
优化技术:
通过彻底重新设计数据处理架构,我们实现了:
这次优化充分证明了: 正确的架构设计比单纯的代码优化更能带来质的飞跃。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.