目录
技术栈概览
关键指标:
- 采集延迟: <5分钟
- 数据可靠性: At-least-once + 幂等处理
- 并发能力: 支持200+店
- 故障恢复: <1小时
实现工具:
- 采集: API Client + Webhook Server
- 传输: Kafka + Flink
- 存储: Doris OLAP
- 监控: Prometheus + Grafana
数据源系统概述
1.1 核心业务系统概览
makefile
200+家门店的多源系统架构:
┌─────────────────────────────────────────────────┐
│ 门店POS系统 (200个) │
│ • 订单数据(日均500-1000单/店) │
│ • 库存扣减(实时) │
│ • 员工班次(实时) │
│ • 会员消费(实时) │
└──────────┬──────────────────────────────────────┘
│
┌─────┴─────┐
│ API/推送 │
↓ ↓
Kafka Webhook
│ │
└─────┬─────┘
↓
┌─────────────────────────────────────────────────┐
│ ERP库存管理系统 (1套) │
│ • 采购订单(日均50+条) │
│ • 库存变动(小时级) │
│ • 供应商管理 │
└──────────┬──────────────────────────────────────┘
│
CDC + API
│
↓
┌─────────────────────────────────────────────────┐
│ CRM会员系统 (1套) │
│ • 会员注册(日均500+) │
│ • 消费记录(实时) │
│ • 积分兑换(实时) │
└──────────┬──────────────────────────────────────┘
│
API推送
│
↓
┌─────────────────────────────────────────────────┐
│ 外卖平台 (美团/饿了么等) │
│ • 订单数据(日均50-200单/店) │
│ • 配送信息(实时GPS) │
│ • 用户评价 │
└──────────┬──────────────────────────────────────┘
│
Rest API
│
↓
┌─────────────────────────────────────────────────┐
│ HRM人力系统 (1套) │
│ • 员工档案 │
│ • 考勤记录(日均200+) │
│ • 工资发放(月度) │
└─────────────────────────────────────────────────┘
1.2 数据集成优先级
| 系统 | 优先级 | 月数据量 | 接入难度 | 关键性 |
|---|---|---|---|---|
| POS | P0 | ~180万 | 中 | 极高 |
| ERP | P0 | ~3万 | 中 | 高 |
| CRM | P1 | ~300万 | 低 | 高 |
| 外卖 | P1 | ~50万 | 高 | 中 |
| HRM | P1 | ~6000 | 低 | 中 |
POS系统数据对接
2.1 POS系统API接口设计
bash
常见POS系统: 二维火、美团收银、新大陆、天龙等
标准API接口 (以通用POS为例):
1. 订单查询接口
GET /api/v1/orders
参数:
• shop_id (门店ID)
• start_time (开始时间)
• end_time (结束时间)
• page_size (每页条数, 默认100)
返回数据:
{
"code": 200,
"data": {
"total": 1000,
"list": [
{
"order_id": "ORD20251130001",
"shop_id": "SHOP001",
"order_time": "2025-11-30 12:30:00",
"order_type": "dine_in",
"table_number": "01",
"customer_id": "CUST123",
"items": [
{
"menu_id": "MENU001",
"menu_name": "红烧肉",
"quantity": 2,
"unit_price": 38.00,
"actual_price": 76.00,
"category": "热菜"
}
],
"total_amount": 190.00,
"discount_amount": 10.00,
"payment_method": "wechat",
"order_status": "paid"
}
]
}
}
2. 库存查询接口
GET /api/v1/inventory/stock
参数:
• shop_id (门店ID)
返回数据:
{
"code": 200,
"data": {
"shop_id": "SHOP001",
"timestamp": "2025-11-30 23:00:00",
"stocks": [
{
"menu_id": "MENU001",
"menu_name": "红烧肉",
"quantity": 45,
"low_threshold": 10,
"status": "normal"
}
]
}
}
3. 员工班次接口
GET /api/v1/shifts
参数:
• shop_id (门店ID)
• date (日期: yyyy-MM-dd)
返回数据:
{
"code": 200,
"data": {
"date": "2025-11-30",
"shifts": [
{
"employee_id": "EMP001",
"employee_name": "张三",
"position": "服务员",
"check_in_time": "10:30:00",
"check_out_time": "18:30:00",
"actual_duration": 480
}
]
}
}
4. 会员接口
GET /api/v1/members/consumption
参数:
• shop_id (门店ID)
返回数据:
{
"code": 200,
"data": {
"members": [
{
"member_id": "M20251000001",
"phone": "13900001111",
"name": "李四",
"member_level": "gold",
"join_date": "2024-01-15",
"total_consumption": 5000.00,
"points_balance": 500
}
]
}
}
2.2 数据采集实现方案
makefile
采用 Webhook推送 + 定时拉取 的混合模式:
模式A: Webhook实时推送 (优先)
┌───────────┐
│ POS系统 │
└─────┬─────┘
│ (订单完成时POST)
↓
┌──────────────────────┐
│ 数据接收服务 │
│ • 验证签名 │
│ • 去重处理 │
│ • 本地缓存 │
└──────┬───────────────┘
│
↓
┌─────────┐
│ Kafka │
└────┬────┘
│
↓
┌──────────────┐
│ Flink处理 │
│ • 清洗 │
│ • 聚合 │
│ • 计算 │
└────┬─────────┘
│
↓
┌─────────┐
│ Doris │
└─────────┘
模式B: 定时拉取 (备选, 断点续传)
├─ 每5分钟拉取一次新订单
├─ 记录上次拉取时间 (断点续传)
└─ 支持失败重试 (3次)
优势:
• 低延迟: Webhook推送秒级
• 高可靠: Kafka持久化 + 本地缓存
• 可容错: 定时拉取补偿遗漏
供应链系统对接
3.1 ERP库存系统API
bash
核心接口:
1. 库存主数据
GET /api/v1/materials
返回: 物料列表(菜品/原材料)
数据量: 100-200个物料
2. 门店库存
GET /api/v1/inventory/by_shop
参数: shop_id
返回: 每家店的当前库存和成本
3. 采购订单
GET /api/v1/purchase_orders
参数: 日期范围
返回: 采购单据(供应商/价格/数量)
4. 收货单
POST /api/v1/goods_receipts
参数: 采购单ID/收货数量/收货地点
返回: 收货确认
5. 出库单
POST /api/v1/goods_issues
参数: 物料ID/出库数量/出库地点
返回: 出库单据ID
同步策略:
主数据: 日同步 (凌晨)
├─ 物料信息 (菜品/成本等)
├─ 供应商信息
└─ 价目表
库存变动: 实时/小时级
├─ 使用CDC (数据库变更捕获)
├─ 或API轮询 (每小时一次)
└─ 双重验证对账
采购订单: 实时推送
├─ 新订单创建 → 推送
├─ 订单状态变更 → 推送
└─ 收货完成 → 推送
外卖平台对接
4.1 主流平台API (以美团为例)
ruby
美团开放平台API:
1. 订单查询
GET https://api.meituanopen.com/order/queryOrder
参数:
• chainId (商户ID)
• storeId (门店ID)
• startDate / endDate
返回:
{
"code": 0,
"data": {
"total": 100,
"orders": [
{
"orderId": "123456789",
"storeId": "123456",
"orderTime": "2025-11-30 12:30:00",
"orderStatus": 5,
"items": [
{
"dishId": "234567",
"dishName": "宫保鸡丁",
"count": 2,
"unitPrice": 28.00,
"totalPrice": 56.00
}
],
"totalAmount": 56.00,
"discount": 5.00,
"actualPayAmount": 51.00,
"deliveryFee": 2.00
}
]
}
}
2. 配送轨迹
GET https://api.meituanopen.com/order/queryTrack
参数: orderId
返回: GPS位置、配送状态等
3. 评价接口
GET https://api.meituanopen.com/review/queryReviews
参数: storeId, startTime, endTime
返回: 用户评价(评分/内容/时间)
采集策略:
├─ 订单: 日末拉取 (避免重复)
├─ 配送: 实时推送 (Webhook)
└─ 评价: 日拉取 (T+1)
4.2 多平台聚合方案
makefile
由于有多个外卖平台(美团/饿了么/抖音等):
统一接口层设计:
┌─────────────────────────┐
│ 应用层 (统一接口) │
│ • 订单查询 │
│ • 配送跟踪 │
│ • 评价分析 │
└────────────┬────────────┘
│
┌────────┼────────┐
↓ ↓ ↓
┌─────┐ ┌──────┐ ┌─────┐
│美团 │ │饿了么│ │抖音 │
└─────┘ └──────┘ └─────┘
API API API
适配器层(Adapter Pattern):
├─ MeituanAdapter
│ ├─ 订单查询 → 统一格式
│ ├─ 配送查询 → 统一格式
│ └─ 评价查询 → 统一格式
│
├─ ElemeAdapter
│ └─ ... (类似)
│
└─ OtherAdapter
└─ ... (类似)
优势:
• 新增平台只需增加一个Adapter
• 应用层逻辑无需改动
• 易于扩展和维护
数据管道架构
5.1 完整的数据流架构
markdown
多源数据统一接入:
源系统 接收层 消息队列 处理层 存储层
─────────────────────────────────────────────────────────
POS API ─→ API Gateway ─→ Kafka ─────→ Flink Streaming ─→ Doris
(签名验证) (pos_order) (清洗+计算) (ODS/DWD)
(去重) (维度关联)
ERP CDC ─→ Canal Server ─→ Kafka ─────→ Flink Streaming ─→ Doris
(Binary Log) (erp_changes)(增量处理) (库存表)
(解析)
CRM API ─→ Webhook ────→ Kafka ─────→ Flink Streaming ─→ Doris
(标准化) (crm_events) (会员数据) (会员维表)
外卖API ─→ API Gateway ─→ Kafka ─────→ Flink Streaming ─→ Doris
(多平台适配) (takeout) (统一处理) (订单事实)
HRM API ─→ API Gateway ─→ Kafka ─────→ Flink Streaming ─→ Doris
(日拉取) (hr_data) (薪资数据) (员工维表)
关键设计:
1. Kafka Topic规划
pos_order_stream (POS订单流)
erp_inventory_changes (库存变动)
crm_member_events (会员事件)
takeout_order_stream (外卖订单)
hr_attendance_daily (考勤数据)
2. Flink处理特性
├─ 并行度: 32 (支持200店并发)
├─ 状态管理: RocksDB后端
├─ Checkpoint: 60秒间隔
└─ 容错: Exactly-Once语义
3. Doris写入
├─ 批量导入: 每分钟一次
├─ 并发度: 16个并发
├─ 副本: 生产3副本, 开发1副本
└─ 压缩: LZ4算法
5.2 故障处理机制
makefile
三层容错设计:
应用层容错:
├─ 幂等性: 每条消息带唯一ID
├─ 去重: 使用Redis缓存去重
└─ 重试: 3次重试+指数退避
消息层容错:
├─ Kafka副本: 3副本策略
├─ 消息保留: 7天历史
└─ 消费补偿: 支持offset重置
数据库层容错:
├─ 事务支持: 两阶段提交
├─ 幂等插入: REPLACE INTO语法
└─ 定期对账: 小时/日/月对账
故障恢复:
POS采集故障:
├─ 本地缓存: 临时堆积数据
├─ Kafka缓冲: 消息持久化
└─ 恢复: 自动重传 + 断点续传
ERP同步故障:
├─ CDC日志: 持久化变更日志
├─ 备用拉取: 小时级API拉取
└─ 恢复: 重新消费CDC日志
数据不一致:
├─ 自动对账: 每小时运行
├─ 差异告警: >0.1%立即告警
└─ 人工审核: 差异修复流程
故障处理与一致性
6.1 端到端数据一致性
makefile
一致性保证链:
源系统(POS) → 采集层 → 消息队列 → 计算层 → 存储层 → 消费端
幂等性设计:
├─ 源端: 消息ID (order_id + timestamp)
├─ 采集: 去重表 (Redis + 24小时过期)
├─ 消息: Kafka事务支持
├─ 计算: 更新而非插入 (幂等)
└─ 存储: INSERT REPLACE (幂等覆盖)
检验机制:
小时级对账:
├─ 比较: POS订单总额 vs Doris中该小时数据
├─ 差异: >0.1% 立即告警
└─ 频率: 每小时自动运行
日级对账:
├─ 逐店逐项对账
├─ 与财务系统对账
└─ 发现差异自动触发修复
版本管理:
├─ 每个数据版本添加版本号
├─ 支持历史版本查询
└─ 重要修改记录在案