phase 5 part 3: mongodb, elasticsearch hybrid search, data-pipeline, nodejs BFF topics with verified examples
This commit is contained in:
1 parent
9eeb10aede
commit
075872e31e
27 files changed
+2405
-52
No files matched your search
@@ -0,0 +1,100 @@
|
||||
---
|
||||
id: backend.data-pipeline.reliability
|
||||
title: 数据管道基础:批处理与流处理、增量同步、限流重试、幂等、数据质量和告警
|
||||
type: lesson
|
||||
domain: backend
|
||||
stack: [data-pipeline]
|
||||
tags: [ETL, 批处理, 流处理, 增量同步, 水位线, 限流, 重试, 幂等, 死信, 数据质量, 告警]
|
||||
level: intermediate
|
||||
prerequisites: [backend.postgresql.index-tx-mvcc, backend.mq.reliability]
|
||||
est_hours: 3
|
||||
related: [backend.data-pipeline.scenario.third-party-sync, backend.data-pipeline.interview, backend.elasticsearch.scenario.kb-search-sync]
|
||||
week: [14]
|
||||
order: 1
|
||||
---
|
||||
|
||||
# 数据管道基础:批处理与流处理、增量同步、限流重试、幂等、数据质量和告警
|
||||
|
||||
> BOSS直聘 2026-10-23 的调研中,部分 AI 应用岗位要求“数据处理 / 数据管道”能力:知识库文档的采集清洗、第三方平台数据对接、报表数据准备。这里讲后端工程师需要掌握的基础,不涉及大数据平台。
|
||||
|
||||
## 解释说明
|
||||
|
||||
### 批处理和流处理
|
||||
|
||||
| | 批处理 | 流处理 |
|
||||
| --- | --- | --- |
|
||||
| 触发 | 定时(每小时 / 每天) | 事件到达即处理 |
|
||||
| 延迟 | 分钟到小时 | 秒级 |
|
||||
| 实现 | 定时任务 + SQL / Python | 消息队列(Kafka / RabbitMQ)+ 消费者,或 CDC |
|
||||
| 适合 | 报表、对账、全量重建 | 搜索同步、实时告警、实时推荐 |
|
||||
|
||||
很多系统两者结合:流处理保证实时,批处理定期对账兜底。
|
||||
|
||||
### 增量同步的关键
|
||||
|
||||
1. **水位线**:记录上次同步到哪里(时间戳 + 主键打破平局),失败后从水位线继续。**水位线只在本批数据成功落库后推进**。
|
||||
2. **限流**:第三方接口有调用频率限制,用令牌桶控制;收到 429 时遵守 `Retry-After`。
|
||||
3. **重试**:区分可重试错误(超时、5xx、429)和不可重试错误(401、参数错误);指数退避 + 抖动(避免大量客户端同时重试),有上限。
|
||||
4. **幂等**:重复运行结果一致——按主键 upsert,并且比较版本号 / 更新时间,旧数据不能覆盖新数据。
|
||||
5. **坏数据**:单条坏数据进入死信表,不阻塞整批;坏数据比例超过阈值说明上游出问题了,应停止并告警。
|
||||
6. **数据质量检查**:行数波动、空值率、取值范围、唯一性、与源头的对账。
|
||||
7. **可观测**:每次运行记录拉取数、写入数、死信数、耗时;失败和质量异常告警。
|
||||
|
||||
### 常用工具(了解)
|
||||
|
||||
定时调度:cron、Celery Beat、APScheduler;编排:Airflow、Dagster、Prefect;CDC:Debezium;数据质量:Great Expectations 一类工具。小团队先用“定时任务 + 本课的这些原则”就够了。
|
||||
|
||||
## 案例
|
||||
|
||||
每 10 分钟从电商平台开放接口同步订单到自己的数据库,供 AI 报表 Agent 查询:接口每秒限 50 次、偶尔超时;有时返回状态值异常的数据;同步中断后要能续跑;不能产生重复订单。
|
||||
|
||||
## 代码示例
|
||||
|
||||
[examples/incremental-sync](examples/incremental-sync/)(只用标准库,`python pipeline.py` 运行,`test_pipeline.py` 6 个测试通过):
|
||||
|
||||
```text
|
||||
第一次:拉取 251,写入 250,死信 1,接口调用 5 次(含 2 次失败重试)
|
||||
第二次(没有新数据):拉取 0
|
||||
orders 表 250 行,水位线 ('2026-10-23T11:00:00', 'bad1')
|
||||
```
|
||||
|
||||
幂等且防止旧版本覆盖:
|
||||
|
||||
```sql
|
||||
INSERT INTO orders (id, amount_cents, status, updated_at) VALUES (:id, :amount_cents, :status, :updated_at)
|
||||
ON CONFLICT(id) DO UPDATE SET amount_cents = excluded.amount_cents, status = excluded.status, updated_at = excluded.updated_at
|
||||
WHERE excluded.updated_at > orders.updated_at
|
||||
```
|
||||
|
||||
重试(指数退避 + 全抖动,遵守 Retry-After):
|
||||
|
||||
```python
|
||||
def with_retry(fn, *, attempts=5, base=0.2, cap=5.0, sleep=time.sleep, rng=None):
|
||||
rng = rng or random.Random()
|
||||
for i in range(attempts):
|
||||
try:
|
||||
return fn()
|
||||
except RetryableError as e:
|
||||
if i == attempts - 1:
|
||||
raise
|
||||
delay = e.retry_after if e.retry_after is not None else rng.uniform(0, min(cap, base * 2 ** i))
|
||||
sleep(delay)
|
||||
```
|
||||
|
||||
质量检查不通过时整批回滚、水位线不前进并告警(见 `test_quality_gate_rolls_back_and_alerts`)。
|
||||
|
||||
## 易错点
|
||||
|
||||
- 先推进水位线再写数据:中途失败就丢数据。
|
||||
- 只用时间戳做水位线:同一秒内有多条数据时会漏或重复;要加主键打破平局。
|
||||
- **迟到数据**:来源系统的事务晚提交,`updated_at` 比水位线还早,被永远跳过。办法:每次往回多拉一个重叠窗口(例如 5 分钟),依赖幂等写入去重;再加定期对账。
|
||||
- 对所有错误都重试,包括 401,结果被对方封禁。
|
||||
- 没有抖动的重试,故障恢复瞬间所有任务一起打过去。
|
||||
- 坏数据直接让整个任务失败,或者相反——静默丢弃没有任何记录。
|
||||
|
||||
## 面试常问
|
||||
|
||||
- 怎么设计一个可以断点续传的增量同步任务?
|
||||
- 怎么保证同步任务幂等?
|
||||
- 第三方接口限流和不稳定怎么处理?
|
||||
- 怎么发现数据质量问题?
|
||||
Reference in new issue
Block a user