diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 000000000..e6edc808b
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,312 @@
+# 响应式ETL框架文档中心
+
+## 📚 文档导航
+
+### 核心设计文档
+
+#### 1. [系统架构设计](reactive-etl-framework-design.md)
+完整的系统架构设计文档,包含:
+- 系统整体架构
+- 核心模块设计(Job、StreamGraph、JobGraph、Scheduler、Executor等)
+- 关键流程时序图
+- 监控运维方案
+- 最佳实践
+
+**推荐阅读顺序**: ⭐️⭐️⭐️⭐️⭐️ 必读
+
+---
+
+#### 2. [数据库设计](database-design.md)
+数据库表结构设计文档(单机版),包含:
+- 13张核心表的详细设计
+- 表关系ER图
+- 索引策略
+- 分区方案
+- 数据保留策略
+
+**推荐阅读顺序**: ⭐️⭐️⭐️⭐️⭐️ 必读
+
+---
+
+#### 3. [数据库建表脚本](database-schema.sql)
+可直接执行的SQL脚本,包含:
+- 所有表的CREATE TABLE语句
+- 索引定义
+- 初始化数据(内置连接器、系统配置、告警规则)
+- 便捷查询视图
+
+**使用方式**:
+```bash
+mysql -u root -p etl_framework < database-schema.sql
+```
+
+---
+
+### StreamGraph配置文档
+
+#### 4. [StreamGraph定义结构说明](graph-definition-examples.md)
+详细的StreamGraph配置说明,包含:
+- 完整的JSON结构定义
+- 所有节点类型详解(Source、Operator、Sink)
+- 配置参数说明
+- 可视化流程图
+- 最佳实践建议
+
+**推荐阅读顺序**: ⭐️⭐️⭐️⭐️ 开发必读
+
+---
+
+#### 5. [JSON配置示例](graph-definition-json-examples.json)
+7个完整的、可直接使用的JSON配置示例:
+1. **简单ETL** - Kafka到MySQL
+2. **实时统计** - 窗口聚合
+3. **数据清洗** - 去重和转换
+4. **多分支处理** - 日志分流
+5. **API数据采集** - HTTP定期拉取
+6. **文件处理** - CSV到JSON
+7. **数据关联** - JOIN操作
+
+**使用方式**: 直接复制粘贴到你的任务配置中
+
+---
+
+#### 6. [JSON示例使用指南](json-examples-guide.md)
+JSON示例的详细使用说明,包含:
+- 每个示例的场景说明
+- 数据流程图
+- 适用场景
+- 配置说明
+- 常见问题解答
+
+**推荐阅读顺序**: ⭐️⭐️⭐️⭐️ 快速上手
+
+---
+
+## 🚀 快速开始
+
+### 第一步:了解系统架构
+阅读 [系统架构设计](reactive-etl-framework-design.md),理解系统的整体设计理念。
+
+### 第二步:初始化数据库
+```bash
+# 创建数据库
+mysql -u root -p
+CREATE DATABASE etl_framework DEFAULT CHARACTER SET utf8mb4;
+
+# 执行建表脚本
+mysql -u root -p etl_framework < database-schema.sql
+```
+
+### 第三步:查看示例
+打开 [JSON配置示例](graph-definition-json-examples.json),选择一个最接近你需求的示例。
+
+### 第四步:创建任务
+参考 [JSON示例使用指南](json-examples-guide.md),修改配置并创建你的第一个ETL任务。
+
+---
+
+## 📖 按角色阅读
+
+### 架构师
+1. [系统架构设计](reactive-etl-framework-design.md) - 了解整体架构
+2. [数据库设计](database-design.md) - 了解数据模型
+
+### 开发人员
+1. [系统架构设计](reactive-etl-framework-design.md) - 核心模块章节
+2. [StreamGraph定义结构说明](graph-definition-examples.md) - 节点类型详解
+3. [JSON示例使用指南](json-examples-guide.md) - 快速上手
+
+### 运维人员
+1. [系统架构设计](reactive-etl-framework-design.md) - 监控运维章节
+2. [数据库设计](database-design.md) - 索引和分区优化
+3. [数据库建表脚本](database-schema.sql) - 执行初始化
+
+### 产品经理
+1. [系统架构设计](reactive-etl-framework-design.md) - 概述和特性
+2. [JSON示例使用指南](json-examples-guide.md) - 场景示例
+
+---
+
+## 🎯 按场景查找
+
+### 场景1: 实时数据采集
+- **Kafka数据采集**: 查看示例1和示例2
+- **API数据拉取**: 查看示例5
+- **文件监控采集**: 查看示例6
+
+### 场景2: 数据转换清洗
+- **简单转换**: 查看示例1(MAP + FILTER)
+- **去重**: 查看示例3(DEDUPLICATE)
+- **数组展开**: 查看示例5(FLATMAP)
+
+### 场景3: 实时统计聚合
+- **窗口聚合**: 查看示例2(WINDOW + AGGREGATE)
+- **分组统计**: 查看示例2(GROUP BY)
+
+### 场景4: 数据关联
+- **JOIN操作**: 查看示例7
+- **维度补全**: 查看示例7
+
+### 场景5: 多目标输出
+- **分支处理**: 查看示例4(多Filter + 多Sink)
+- **双写**: 查看示例2(MySQL + Redis)
+
+---
+
+## 🔧 配置速查
+
+### 常用Source配置
+
+```json
+// Kafka Source
+{
+ "operator_type": "KAFKA_SOURCE",
+ "config": {
+ "datasource_id": "kafka-prod",
+ "topics": ["topic-name"],
+ "group_id": "consumer-group"
+ }
+}
+
+// JDBC Source
+{
+ "operator_type": "JDBC_SOURCE",
+ "config": {
+ "datasource_id": "mysql-prod",
+ "query": "SELECT * FROM table WHERE ...",
+ "fetch_size": 1000
+ }
+}
+```
+
+### 常用Operator配置
+
+```json
+// MAP
+{
+ "operator_type": "MAP",
+ "config": {
+ "function_class": "com.example.YourFunction"
+ }
+}
+
+// FILTER
+{
+ "operator_type": "FILTER",
+ "config": {
+ "predicate_expression": "field > 100"
+ }
+}
+
+// AGGREGATE
+{
+ "operator_type": "AGGREGATE",
+ "config": {
+ "group_by_fields": ["city"],
+ "aggregations": [
+ {"field": "amount", "function": "SUM"}
+ ]
+ }
+}
+```
+
+### 常用Sink配置
+
+```json
+// JDBC Sink
+{
+ "operator_type": "JDBC_SINK",
+ "config": {
+ "datasource_id": "mysql-warehouse",
+ "table": "target_table",
+ "batch_size": 100,
+ "write_mode": "INSERT"
+ }
+}
+
+// Kafka Sink
+{
+ "operator_type": "KAFKA_SINK",
+ "config": {
+ "datasource_id": "kafka-prod",
+ "topic": "output-topic",
+ "batch_size": 100
+ }
+}
+```
+
+---
+
+## 📊 表结构速查
+
+### 核心表(13张)
+
+| 表名 | 说明 | 关键字段 |
+| --- | --- | --- |
+| etl_job | 任务定义 | job_id, job_status |
+| etl_job_instance | 运行实例 | instance_id, job_id |
+| etl_job_schedule | 调度配置 | schedule_type, cron_expression |
+| etl_stream_graph | 流图定义 | graph_id, graph_definition |
+| etl_connector | 连接器注册 | connector_id, connector_type |
+| etl_datasource | 数据源配置 | datasource_id, connection_config |
+| etl_checkpoint | 检查点 | checkpoint_id, instance_id |
+| etl_job_metrics | 运行指标 | job_id, metric_time |
+| etl_system_config | 系统配置 | config_key, config_value |
+| etl_alert_rule | 告警规则 | rule_id, rule_type |
+| etl_alert_record | 告警记录 | alert_id, alert_time |
+| etl_user | 用户 | user_id, username |
+| etl_operation_log | 操作日志 | operation_type, resource_type |
+
+---
+
+## ❓ 常见问题
+
+### Q1: 数据源配置在哪里?
+在`etl_datasource`表中配置,然后在graph_definition中通过`datasource_id`引用。
+
+### Q2: 如何添加自定义算子?
+在nodes配置中指定你的`function_class`,框架会通过反射加载。
+
+### Q3: 支持哪些数据源?
+内置支持:JDBC、Kafka、HTTP、File、Redis、Elasticsearch。可通过SPI机制扩展。
+
+### Q4: 如何配置检查点?
+在`etl_job`表的`checkpoint_enabled`字段或graph_definition的`global_config`中配置。
+
+### Q5: 如何监控任务运行?
+查看`etl_job_instance`和`etl_job_metrics`表,或使用Prometheus等监控系统。
+
+---
+
+## 🔗 相关资源
+
+### 技术栈
+- [Project Reactor](https://projectreactor.io/) - 响应式编程框架
+- [Apache Kafka](https://kafka.apache.org/) - 消息队列
+- [MySQL](https://www.mysql.com/) - 关系型数据库
+- [Elasticsearch](https://www.elastic.co/) - 搜索引擎
+
+### 参考项目
+- [Apache Flink](https://flink.apache.org/) - 分布式流处理框架
+- [Spring Cloud Data Flow](https://spring.io/projects/spring-cloud-dataflow) - 数据流编排
+
+---
+
+## 📝 文档版本
+
+| 版本 | 日期 | 说明 |
+| --- | --- | --- |
+| v1.0 | 2025-11-09 | 初始版本 |
+| v2.0 | 2025-11-09 | 简化为单机版架构 |
+
+---
+
+## 👥 贡献者
+
+ETL Framework Team
+
+---
+
+## 📧 联系方式
+
+如有问题或建议,请联系项目维护者。
diff --git a/docs/database-design.md b/docs/database-design.md
new file mode 100644
index 000000000..03989c74a
--- /dev/null
+++ b/docs/database-design.md
@@ -0,0 +1,666 @@
+# 响应式ETL框架 - 数据库设计文档(单机版)
+
+## 1. 概述
+
+本文档描述了响应式ETL框架的数据库表结构设计。该框架采用**单机执行模式**,即一个Job作为最小执行单元,在单个实例上完整运行,不涉及分布式算子调度。
+
+### 1.1 设计原则
+
+- **单机执行**: 每个Job在一个实例上完整执行,不会将算子分散到不同节点
+- **简洁高效**: 去除分布式相关的复杂设计,保持表结构简洁
+- **易于管理**: 降低运维复杂度,适合中小规模数据处理
+- **完整功能**: 支持任务调度、检查点、监控告警等核心功能
+
+### 1.2 数据库选型
+
+- **数据库**: MySQL 8.0+
+- **字符集**: utf8mb4
+- **存储引擎**: InnoDB
+- **时区**: 统一使用UTC或Asia/Shanghai
+
+### 1.3 表分类概览
+
+```mermaid
+graph TB
+ DB[ETL Database
单机版]
+
+ DB --> JOB[任务管理
3张表]
+ DB --> GRAPH[图结构
1张表]
+ DB --> CONN[连接器
2张表]
+ DB --> CP[检查点
1张表]
+ DB --> METRICS[监控指标
1张表]
+ DB --> SYS[系统配置
3张表]
+ DB --> USER[用户审计
2张表]
+
+ JOB --> J1[etl_job
任务定义]
+ JOB --> J2[etl_job_instance
运行实例]
+ JOB --> J3[etl_job_schedule
调度配置]
+
+ GRAPH --> G1[etl_stream_graph
流图定义]
+
+ CONN --> C1[etl_connector
连接器注册]
+ CONN --> C2[etl_datasource
数据源配置]
+
+ CP --> CP1[etl_checkpoint
检查点]
+
+ METRICS --> M1[etl_job_metrics
运行指标]
+
+ SYS --> S1[etl_system_config
系统配置]
+ SYS --> S2[etl_alert_rule
告警规则]
+ SYS --> S3[etl_alert_record
告警记录]
+
+ USER --> U1[etl_user
用户]
+ USER --> U2[etl_operation_log
操作日志]
+```
+
+## 2. 任务管理相关表
+
+### 2.1 etl_job - 任务定义表
+
+**用途**: 存储ETL任务的定义信息和配置
+
+**核心设计**:
+- 一个Job包含完整的Source → Operators → Sink处理链
+- 使用JSON字段存储Source、Operators、Sink配置,灵活且易于扩展
+- 不需要并行度、分区等分布式概念
+
+**关键字段说明**:
+
+| 字段 | 类型 | 说明 |
+| --- | --- | --- |
+| job_id | VARCHAR(64) | 任务唯一标识,建议UUID |
+| job_type | VARCHAR(32) | STREAMING(流式)/BATCH(批处理) |
+| job_status | VARCHAR(32) | CREATED/SCHEDULED/RUNNING/PAUSED/COMPLETED/FAILED/CANCELLED |
+| stream_graph_id | VARCHAR(64) | 关联的StreamGraph ID |
+| source_config | JSON | Source配置,包含连接器类型、数据源ID、读取参数等 |
+| operators_config | JSON | Operators配置数组,按顺序执行 |
+| sink_config | JSON | Sink配置,包含连接器类型、目标数据源、写入参数等 |
+| restart_strategy | VARCHAR(32) | 重启策略: FIXED_DELAY/EXPONENTIAL_BACKOFF/NO_RESTART |
+| checkpoint_enabled | TINYINT | 是否启用检查点 |
+
+**配置示例**:
+
+```json
+{
+ "source_config": {
+ "connector_type": "kafka",
+ "datasource_id": "kafka-prod",
+ "topics": ["user-events"],
+ "group_id": "etl-consumer",
+ "poll_timeout_ms": 1000
+ },
+ "operators_config": [
+ {
+ "operator_type": "MAP",
+ "name": "parse-json",
+ "function": "com.example.ParseJsonFunction"
+ },
+ {
+ "operator_type": "FILTER",
+ "name": "filter-active",
+ "predicate": "user.isActive == true"
+ },
+ {
+ "operator_type": "AGGREGATE",
+ "name": "count-by-city",
+ "window_size": "5m",
+ "group_by": "city"
+ }
+ ],
+ "sink_config": {
+ "connector_type": "jdbc",
+ "datasource_id": "mysql-warehouse",
+ "table": "user_stats",
+ "batch_size": 100,
+ "flush_interval_ms": 5000
+ }
+}
+```
+
+### 2.2 etl_job_instance - 任务实例表
+
+**用途**: 记录每次Job运行的实例信息
+
+**核心设计**:
+- 一个Job可以有多次运行实例
+- 记录运行主机、进程ID等信息,便于定位问题
+- 记录核心指标:读取、处理、写入记录数
+
+**关键字段说明**:
+
+| 字段 | 类型 | 说明 |
+| --- | --- | --- |
+| instance_id | VARCHAR(64) | 实例唯一标识 |
+| job_id | VARCHAR(64) | 所属任务ID |
+| instance_status | VARCHAR(32) | RUNNING/COMPLETED/FAILED/CANCELLED |
+| host_address | VARCHAR(128) | 运行主机地址,如 192.168.1.100 |
+| process_id | VARCHAR(64) | 进程PID |
+| start_time | DATETIME | 开始时间 |
+| end_time | DATETIME | 结束时间 |
+| duration_ms | BIGINT | 执行时长(毫秒) |
+| records_read | BIGINT | 读取记录数 |
+| records_processed | BIGINT | 处理记录数 |
+| records_written | BIGINT | 写入记录数 |
+| last_checkpoint_id | VARCHAR(64) | 最后检查点ID,用于故障恢复 |
+
+**使用场景**:
+- 任务执行历史查询
+- 故障排查和问题定位
+- 性能分析和统计报表
+
+### 2.3 etl_job_schedule - 任务调度配置表
+
+**用途**: 管理任务的调度策略
+
+**核心设计**:
+- 支持立即执行、定时执行、手动执行三种模式
+- 一个Job对应一个调度配置(1:1关系)
+- 简化了依赖调度和事件触发(可在应用层实现)
+
+**关键字段说明**:
+
+| 字段 | 类型 | 说明 |
+| --- | --- | --- |
+| schedule_type | VARCHAR(32) | IMMEDIATE(立即)/CRON(定时)/MANUAL(手动) |
+| cron_expression | VARCHAR(128) | Cron表达式,如 "0 0 * * * ?" |
+| next_fire_time | DATETIME | 下次触发时间 |
+| fire_count | BIGINT | 已触发次数 |
+
+**Cron表达式示例**:
+- `0 0 * * * ?` - 每小时执行
+- `0 0 1 * * ?` - 每天凌晨1点执行
+- `0 */5 * * * ?` - 每5分钟执行
+
+## 3. 图结构相关表
+
+### 3.1 etl_stream_graph - StreamGraph定义表
+
+**用途**: 存储任务的数据流图定义
+
+**核心设计**:
+- StreamGraph是逻辑执行图,描述Source → Operators → Sink的数据流向
+- 使用JSON完整存储图结构,包括节点和边
+- 单机模式下不需要JobGraph优化,直接使用StreamGraph执行
+
+**关键字段说明**:
+
+| 字段 | 类型 | 说明 |
+| --- | --- | --- |
+| graph_id | VARCHAR(64) | 图唯一标识 |
+| job_id | VARCHAR(64) | 关联的任务ID |
+| graph_definition | JSON | 完整的图定义 |
+
+**图定义JSON结构**:
+
+```json
+{
+ "nodes": [
+ {
+ "node_id": "source-1",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "config": {...}
+ },
+ {
+ "node_id": "map-1",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "config": {...}
+ },
+ {
+ "node_id": "sink-1",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "config": {...}
+ }
+ ],
+ "edges": [
+ {
+ "source": "source-1",
+ "target": "map-1"
+ },
+ {
+ "source": "map-1",
+ "target": "sink-1"
+ }
+ ]
+}
+```
+
+**设计简化**:
+- 去除了并行度、分区策略等分布式概念
+- 不需要算子链优化(Operator Chain)
+- 不需要资源分配和调度
+
+## 4. 连接器配置相关表
+
+### 4.1 etl_connector - 连接器注册表
+
+**用途**: 注册系统支持的所有连接器
+
+**核心设计**:
+- 内置连接器随系统初始化
+- 支持自定义连接器通过SPI机制注册
+- 一个连接器可以同时支持Source和Sink
+
+**内置连接器**:
+
+| 连接器类型 | 支持Source | 支持Sink | 说明 |
+| --- | --- | --- | --- |
+| JDBC | ✓ | ✓ | 关系型数据库 |
+| KAFKA | ✓ | ✓ | 消息队列 |
+| HTTP | ✓ | ✓ | REST API |
+| FILE | ✓ | ✓ | 文件系统 |
+| REDIS | ✓ | ✓ | 缓存 |
+| ELASTICSEARCH | ✓ | ✓ | 搜索引擎 |
+
+### 4.2 etl_datasource - 数据源配置表
+
+**用途**: 存储具体的数据源连接配置
+
+**核心设计**:
+- 一个连接器可以配置多个数据源实例
+- 数据源配置可以在多个Job间共享
+- 敏感信息(密码)需要加密存储
+
+**配置示例**:
+
+```json
+{
+ "connection_config": {
+ "url": "jdbc:mysql://localhost:3306/test",
+ "username": "root",
+ "password": "encrypted_password",
+ "driver": "com.mysql.cj.jdbc.Driver",
+ "pool": {
+ "maxSize": 20,
+ "maxIdleTime": "30m"
+ }
+ }
+}
+```
+
+## 5. 检查点相关表
+
+### 5.1 etl_checkpoint - 检查点表
+
+**用途**: 记录检查点信息,用于故障恢复
+
+**核心设计**:
+- 周期性自动创建检查点或手动触发
+- 小状态直接存储在数据库(state_snapshot字段)
+- 大状态存储在文件系统,数据库记录路径
+
+**关键字段说明**:
+
+| 字段 | 类型 | 说明 |
+| --- | --- | --- |
+| checkpoint_id | VARCHAR(64) | 检查点唯一标识 |
+| instance_id | VARCHAR(64) | 所属实例ID |
+| checkpoint_type | VARCHAR(32) | AUTO(自动)/MANUAL(手动) |
+| state_size_bytes | BIGINT | 状态大小 |
+| storage_path | VARCHAR(512) | 大状态存储路径 |
+| state_snapshot | JSON | 小状态直接存储 |
+
+**使用场景**:
+- Job失败后从最近的检查点恢复
+- 手动保存点用于版本升级
+- 状态迁移和备份
+
+**保留策略**:
+- 默认保留最近5个检查点
+- 定期清理过期检查点
+
+## 6. 监控指标相关表
+
+### 6.1 etl_job_metrics - 任务运行指标表
+
+**用途**: 记录任务运行时的监控指标
+
+**核心设计**:
+- 单机模式只需要Job级别指标,不需要算子级别指标
+- 定期采集(如每10秒)存储一条记录
+- 用于实时监控和历史趋势分析
+
+**关键指标**:
+
+| 指标类别 | 字段 | 说明 |
+| --- | --- | --- |
+| 吞吐量 | records_read_rate | 读取速率(记录/秒) |
+| 吞吐量 | records_write_rate | 写入速率(记录/秒) |
+| 延迟 | processing_latency_ms | 处理延迟(毫秒) |
+| 错误 | error_count | 错误次数 |
+| 背压 | backpressure_count | 背压次数 |
+| 资源 | jvm_heap_used_mb | JVM堆内存使用 |
+| 资源 | cpu_usage_percent | CPU使用率 |
+| 资源 | thread_count | 线程数 |
+
+**数据保留**:
+- 详细指标保留30天
+- 可以聚合后长期保存
+
+## 7. 系统配置和告警
+
+### 7.1 etl_system_config - 系统配置表
+
+**用途**: 存储系统全局配置
+
+**配置分组**:
+
+| 分组 | 配置项 | 说明 |
+| --- | --- | --- |
+| EXECUTOR | thread.pool.core.size | 线程池核心大小 |
+| EXECUTOR | thread.pool.max.size | 线程池最大大小 |
+| CHECKPOINT | checkpoint.interval.seconds | 检查点间隔 |
+| CHECKPOINT | checkpoint.retention.count | 保留检查点数量 |
+| METRICS | metrics.collect.interval.seconds | 指标采集间隔 |
+
+### 7.2 etl_alert_rule - 告警规则表
+
+**用途**: 定义监控告警规则
+
+**支持的告警类型**:
+
+| 告警类型 | 说明 | 条件示例 |
+| --- | --- | --- |
+| JOB_FAILED | 任务失败 | instance_status == FAILED |
+| JOB_TIMEOUT | 任务超时 | duration_ms > 3600000 |
+| HIGH_ERROR_RATE | 高错误率 | error_count / records_read_total > 0.01 |
+| CHECKPOINT_FAILED | 检查点失败 | checkpoint_status == FAILED |
+
+**通知渠道**:
+- EMAIL: 邮件通知
+- SMS: 短信通知
+- WEBHOOK: Webhook回调
+- DINGTALK: 钉钉机器人
+
+### 7.3 etl_alert_record - 告警记录表
+
+**用途**: 记录触发的告警
+
+**核心功能**:
+- 告警历史追溯
+- 告警状态管理(已解决/未解决)
+- 通知发送状态跟踪
+
+## 8. 表关系ER图
+
+```mermaid
+erDiagram
+ etl_job ||--o{ etl_job_instance : "1:N 一个任务多次运行"
+ etl_job ||--|| etl_job_schedule : "1:1 一个任务一个调度"
+ etl_job ||--|| etl_stream_graph : "1:1 一个任务一个图"
+
+ etl_job_instance ||--o{ etl_checkpoint : "1:N 一次运行多个检查点"
+ etl_job_instance ||--o{ etl_job_metrics : "1:N 一次运行多条指标"
+
+ etl_connector ||--o{ etl_datasource : "1:N 一个连接器多个数据源"
+
+ etl_alert_rule ||--o{ etl_alert_record : "1:N 一个规则多条记录"
+
+ etl_user ||--o{ etl_operation_log : "1:N 一个用户多条日志"
+```
+
+## 9. 核心视图
+
+### 9.1 v_job_instance_stats - 任务实例统计视图
+
+**用途**: 快速查询任务的执行统计信息
+
+```sql
+SELECT * FROM v_job_instance_stats WHERE job_id = 'xxx';
+```
+
+**返回字段**:
+- total_runs: 总运行次数
+- success_runs: 成功次数
+- failed_runs: 失败次数
+- avg_duration_ms: 平均执行时长
+- last_run_time: 最后运行时间
+
+### 9.2 v_running_jobs - 当前运行任务视图
+
+**用途**: 查看当前正在运行的任务
+
+```sql
+SELECT * FROM v_running_jobs ORDER BY start_time DESC;
+```
+
+**返回字段**:
+- instance_id: 实例ID
+- job_name: 任务名称
+- running_seconds: 已运行秒数
+- records_read/processed/written: 实时统计
+
+## 10. 索引策略
+
+### 10.1 主键索引
+所有表使用自增主键`id`,提供快速行定位。
+
+### 10.2 唯一索引
+业务唯一标识字段:
+- job_id, instance_id, checkpoint_id等
+- 保证数据唯一性,避免重复
+
+### 10.3 查询索引
+
+**高频查询字段**:
+```sql
+-- 任务状态查询
+KEY `idx_job_status` (`job_status`)
+
+-- 时间范围查询
+KEY `idx_start_time` (`start_time`)
+
+-- 关联查询
+KEY `idx_job_id` (`job_id`)
+```
+
+**组合索引**(根据实际查询优化):
+```sql
+-- 任务实例查询
+ALTER TABLE etl_job_instance
+ADD INDEX idx_job_status_time (job_id, instance_status, start_time);
+
+-- 指标查询
+ALTER TABLE etl_job_metrics
+ADD INDEX idx_instance_metric_time (instance_id, metric_time);
+```
+
+## 11. 分区策略
+
+对于数据量大的表,建议按时间分区:
+
+### 11.1 指标表分区
+
+```sql
+ALTER TABLE etl_job_metrics
+PARTITION BY RANGE (TO_DAYS(metric_time)) (
+ PARTITION p202501 VALUES LESS THAN (TO_DAYS('2025-02-01')),
+ PARTITION p202502 VALUES LESS THAN (TO_DAYS('2025-03-01')),
+ PARTITION p202503 VALUES LESS THAN (TO_DAYS('2025-04-01')),
+ PARTITION p_future VALUES LESS THAN MAXVALUE
+);
+```
+
+### 11.2 日志表分区
+
+```sql
+ALTER TABLE etl_operation_log
+PARTITION BY RANGE (TO_DAYS(operation_time)) (
+ PARTITION p202501 VALUES LESS THAN (TO_DAYS('2025-02-01')),
+ PARTITION p202502 VALUES LESS THAN (TO_DAYS('2025-03-01')),
+ PARTITION p_future VALUES LESS THAN MAXVALUE
+);
+```
+
+### 11.3 分区维护
+
+```sql
+-- 添加新分区
+ALTER TABLE etl_job_metrics
+ADD PARTITION (PARTITION p202504 VALUES LESS THAN (TO_DAYS('2025-05-01')));
+
+-- 删除旧分区(保留6个月)
+ALTER TABLE etl_job_metrics DROP PARTITION p202410;
+```
+
+## 12. 数据保留策略
+
+| 表名 | 保留时长 | 清理策略 |
+| --- | --- | --- |
+| etl_job | 永久(软删除) | 定期归档已删除任务 |
+| etl_job_instance | 6个月 | 归档旧数据或删除 |
+| etl_checkpoint | 最近5个 | 自动清理旧检查点 |
+| etl_job_metrics | 30天 | 删除或聚合存储 |
+| etl_alert_record | 6个月 | 归档历史告警 |
+| etl_operation_log | 1年 | 归档审计日志 |
+
+## 13. 性能优化建议
+
+### 13.1 查询优化
+- 避免SELECT *,只查询需要的字段
+- 合理使用LIMIT限制结果集
+- 索引覆盖查询,避免回表
+- 大表JOIN使用索引字段
+
+### 13.2 写入优化
+- 批量插入代替单条插入
+- 使用LOAD DATA INFILE导入大量数据
+- 异步写入指标和日志
+- 定期执行OPTIMIZE TABLE
+
+### 13.3 JSON字段使用
+- 不要在JSON字段上建索引
+- 避免在WHERE条件中使用JSON函数
+- 考虑将高频查询字段提取为独立列
+
+### 13.4 连接池配置
+```properties
+# HikariCP推荐配置
+maximumPoolSize=20
+minimumIdle=5
+connectionTimeout=30000
+idleTimeout=600000
+maxLifetime=1800000
+```
+
+## 14. 安全考虑
+
+### 14.1 敏感数据加密
+```java
+// 密码加密示例
+String encrypted = AESUtil.encrypt(password, secretKey);
+
+// BCrypt密码哈希
+String hashed = BCrypt.hashpw(password, BCrypt.gensalt());
+```
+
+### 14.2 SQL注入防护
+- 使用PreparedStatement
+- 参数化查询
+- 输入验证和过滤
+
+### 14.3 访问控制
+- 应用层使用专用数据库账号
+- 最小权限原则
+- 定期审计数据库访问日志
+
+## 15. 备份恢复
+
+### 15.1 备份策略
+
+**全量备份(每日)**:
+```bash
+mysqldump -u root -p --single-transaction \
+ --master-data=2 \
+ etl_framework > backup_$(date +%Y%m%d).sql
+```
+
+**增量备份(实时)**:
+```bash
+# 开启binlog
+[mysqld]
+log-bin=mysql-bin
+binlog_format=ROW
+expire_logs_days=7
+```
+
+### 15.2 恢复演练
+
+**恢复全量备份**:
+```bash
+mysql -u root -p etl_framework < backup_20250109.sql
+```
+
+**恢复到指定时间点**:
+```bash
+mysqlbinlog --start-datetime="2025-01-09 10:00:00" \
+ --stop-datetime="2025-01-09 11:00:00" \
+ mysql-bin.000001 | mysql -u root -p etl_framework
+```
+
+## 16. 初始化步骤
+
+### 步骤1: 创建数据库
+
+```sql
+CREATE DATABASE etl_framework
+DEFAULT CHARACTER SET utf8mb4
+COLLATE utf8mb4_unicode_ci;
+```
+
+### 步骤2: 执行建表脚本
+
+```bash
+mysql -u root -p etl_framework < docs/database-schema.sql
+```
+
+### 步骤3: 验证初始化
+
+```sql
+-- 查看表数量(应该是13张表)
+SELECT COUNT(*) FROM information_schema.tables
+WHERE table_schema = 'etl_framework';
+
+-- 查看内置连接器
+SELECT connector_id, connector_name, connector_type
+FROM etl_connector WHERE is_builtin = 1;
+
+-- 查看系统配置
+SELECT config_key, config_value, config_group
+FROM etl_system_config;
+```
+
+## 17. 常见问题
+
+### Q1: 为什么不使用分布式架构?
+**A**: 单机架构更简单,适合中小规模数据处理。降低了系统复杂度,更容易运维和调试。对于大规模数据处理,可以通过水平扩展多个独立实例实现。
+
+### Q2: 如何实现Job的水平扩展?
+**A**: 可以部署多个ETL实例,每个实例运行不同的Job。通过调度器分配Job到不同实例,实现简单的负载均衡。
+
+### Q3: 检查点数据存储在哪里?
+**A**:
+- 小状态(<1MB): 直接存储在数据库的state_snapshot字段
+- 大状态(>1MB): 存储在文件系统,数据库记录路径
+
+### Q4: 如何处理Job失败?
+**A**:
+1. 根据restart_strategy自动重启
+2. 从最后一个成功的checkpoint恢复
+3. 触发告警通知相关人员
+4. 记录详细的错误信息和堆栈
+
+### Q5: 表结构如何升级?
+**A**:
+1. 使用版本控制管理SQL脚本
+2. 使用Flyway或Liquibase进行数据库迁移
+3. 保持向后兼容,使用ALTER TABLE而非DROP TABLE
+4. 在测试环境充分验证后再上生产
+
+---
+
+**文档版本**: v2.0(单机版)
+**最后更新**: 2025-11-09
+**维护者**: ETL Framework Team
diff --git a/docs/database-schema.sql b/docs/database-schema.sql
new file mode 100644
index 000000000..ca5fb1ab0
--- /dev/null
+++ b/docs/database-schema.sql
@@ -0,0 +1,420 @@
+-- =============================================
+-- 响应式ETL框架 - 数据库表结构设计(单机版)
+-- 版本: v2.0
+-- 创建日期: 2025-11-09
+-- 说明: 单机执行模式,一个Job作为最小执行单元
+-- =============================================
+
+-- =============================================
+-- 1. 任务管理相关表
+-- =============================================
+
+-- 1.1 任务定义表
+CREATE TABLE `etl_job` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `job_id` VARCHAR(64) NOT NULL COMMENT '任务唯一标识',
+ `job_name` VARCHAR(128) NOT NULL COMMENT '任务名称',
+ `job_type` VARCHAR(32) NOT NULL COMMENT '任务类型: STREAMING/BATCH',
+ `job_status` VARCHAR(32) NOT NULL DEFAULT 'CREATED' COMMENT '任务状态: CREATED/SCHEDULED/RUNNING/PAUSED/COMPLETED/FAILED/CANCELLED',
+ `description` TEXT COMMENT '任务描述',
+ `stream_graph_id` VARCHAR(64) COMMENT 'StreamGraph ID',
+ `restart_strategy` VARCHAR(32) DEFAULT 'FIXED_DELAY' COMMENT '重启策略: FIXED_DELAY/EXPONENTIAL_BACKOFF/NO_RESTART',
+ `restart_attempts` INT DEFAULT 3 COMMENT '最大重启次数',
+ `restart_delay_seconds` INT DEFAULT 10 COMMENT '重启延迟(秒)',
+ `checkpoint_enabled` TINYINT DEFAULT 1 COMMENT '是否启用检查点: 0-否, 1-是',
+ `checkpoint_interval_seconds` INT DEFAULT 60 COMMENT '检查点间隔(秒)',
+ `source_config` JSON COMMENT 'Source配置(JSON)',
+ `operators_config` JSON COMMENT 'Operators配置列表(JSON)',
+ `sink_config` JSON COMMENT 'Sink配置(JSON)',
+ `job_config` JSON COMMENT '任务全局配置(JSON)',
+ `creator` VARCHAR(64) COMMENT '创建人',
+ `updater` VARCHAR(64) COMMENT '更新人',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `is_deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除: 0-否, 1-是',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_job_id` (`job_id`),
+ KEY `idx_job_name` (`job_name`),
+ KEY `idx_job_status` (`job_status`),
+ KEY `idx_create_time` (`create_time`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='ETL任务定义表';
+
+-- 1.2 任务实例表(记录每个Job的运行实例)
+CREATE TABLE `etl_job_instance` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `instance_id` VARCHAR(64) NOT NULL COMMENT '实例ID',
+ `job_id` VARCHAR(64) NOT NULL COMMENT '任务ID',
+ `job_name` VARCHAR(128) NOT NULL COMMENT '任务名称',
+ `instance_status` VARCHAR(32) NOT NULL COMMENT '实例状态: RUNNING/COMPLETED/FAILED/CANCELLED',
+ `host_address` VARCHAR(128) COMMENT '运行主机地址',
+ `process_id` VARCHAR(64) COMMENT '进程ID',
+ `start_time` DATETIME NOT NULL COMMENT '开始时间',
+ `end_time` DATETIME COMMENT '结束时间',
+ `duration_ms` BIGINT COMMENT '执行时长(毫秒)',
+ `records_read` BIGINT DEFAULT 0 COMMENT '读取记录数',
+ `records_processed` BIGINT DEFAULT 0 COMMENT '处理记录数',
+ `records_written` BIGINT DEFAULT 0 COMMENT '写入记录数',
+ `records_filtered` BIGINT DEFAULT 0 COMMENT '过滤记录数',
+ `records_failed` BIGINT DEFAULT 0 COMMENT '失败记录数',
+ `error_message` TEXT COMMENT '错误信息',
+ `error_stack_trace` TEXT COMMENT '错误堆栈',
+ `last_checkpoint_id` VARCHAR(64) COMMENT '最后检查点ID',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_instance_id` (`instance_id`),
+ KEY `idx_job_id` (`job_id`),
+ KEY `idx_status` (`instance_status`),
+ KEY `idx_start_time` (`start_time`),
+ KEY `idx_host` (`host_address`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='任务实例表';
+
+-- 1.3 任务调度配置表
+CREATE TABLE `etl_job_schedule` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `schedule_id` VARCHAR(64) NOT NULL COMMENT '调度ID',
+ `job_id` VARCHAR(64) NOT NULL COMMENT '任务ID',
+ `schedule_type` VARCHAR(32) NOT NULL COMMENT '调度类型: IMMEDIATE/CRON/MANUAL',
+ `schedule_enabled` TINYINT NOT NULL DEFAULT 1 COMMENT '是否启用: 0-否, 1-是',
+ `cron_expression` VARCHAR(128) COMMENT 'Cron表达式',
+ `timezone` VARCHAR(64) DEFAULT 'Asia/Shanghai' COMMENT '时区',
+ `next_fire_time` DATETIME COMMENT '下次触发时间',
+ `last_fire_time` DATETIME COMMENT '上次触发时间',
+ `fire_count` BIGINT DEFAULT 0 COMMENT '触发次数',
+ `creator` VARCHAR(64) COMMENT '创建人',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_schedule_id` (`schedule_id`),
+ UNIQUE KEY `uk_job_id` (`job_id`),
+ KEY `idx_schedule_type` (`schedule_type`),
+ KEY `idx_next_fire_time` (`next_fire_time`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='任务调度配置表';
+
+-- =============================================
+-- 2. 图结构相关表(简化)
+-- =============================================
+
+-- 2.1 StreamGraph表
+CREATE TABLE `etl_stream_graph` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `graph_id` VARCHAR(64) NOT NULL COMMENT '图ID',
+ `graph_name` VARCHAR(128) NOT NULL COMMENT '图名称',
+ `job_id` VARCHAR(64) COMMENT '关联任务ID',
+ `graph_definition` JSON NOT NULL COMMENT '图定义(完整的节点和边JSON)',
+ `description` TEXT COMMENT '描述',
+ `creator` VARCHAR(64) COMMENT '创建人',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_graph_id` (`graph_id`),
+ KEY `idx_job_id` (`job_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='StreamGraph定义表';
+
+-- =============================================
+-- 3. 连接器配置相关表
+-- =============================================
+
+-- 3.1 连接器注册表
+CREATE TABLE `etl_connector` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `connector_id` VARCHAR(64) NOT NULL COMMENT '连接器ID',
+ `connector_name` VARCHAR(128) NOT NULL COMMENT '连接器名称',
+ `connector_type` VARCHAR(64) NOT NULL COMMENT '连接器类型: JDBC/KAFKA/HTTP/FILE/REDIS/ELASTICSEARCH等',
+ `connector_class` VARCHAR(256) NOT NULL COMMENT '连接器实现类全限定名',
+ `version` VARCHAR(32) DEFAULT '1.0.0' COMMENT '版本号',
+ `description` TEXT COMMENT '描述',
+ `support_source` TINYINT DEFAULT 0 COMMENT '是否支持Source: 0-否, 1-是',
+ `support_sink` TINYINT DEFAULT 0 COMMENT '是否支持Sink: 0-否, 1-是',
+ `config_schema` JSON COMMENT '配置Schema定义(JSON Schema)',
+ `is_builtin` TINYINT DEFAULT 0 COMMENT '是否内置: 0-否, 1-是',
+ `is_enabled` TINYINT DEFAULT 1 COMMENT '是否启用: 0-否, 1-是',
+ `creator` VARCHAR(64) COMMENT '创建人',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_connector_id` (`connector_id`),
+ KEY `idx_connector_type` (`connector_type`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='连接器注册表';
+
+-- 3.2 数据源配置表
+CREATE TABLE `etl_datasource` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `datasource_id` VARCHAR(64) NOT NULL COMMENT '数据源ID',
+ `datasource_name` VARCHAR(128) NOT NULL COMMENT '数据源名称',
+ `connector_id` VARCHAR(64) NOT NULL COMMENT '连接器ID',
+ `datasource_type` VARCHAR(64) NOT NULL COMMENT '数据源类型',
+ `connection_config` JSON NOT NULL COMMENT '连接配置(JSON)',
+ `description` TEXT COMMENT '描述',
+ `is_enabled` TINYINT DEFAULT 1 COMMENT '是否启用: 0-否, 1-是',
+ `creator` VARCHAR(64) COMMENT '创建人',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_datasource_id` (`datasource_id`),
+ KEY `idx_connector_id` (`connector_id`),
+ KEY `idx_datasource_name` (`datasource_name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据源配置表';
+
+-- =============================================
+-- 4. 检查点相关表(简化)
+-- =============================================
+
+-- 4.1 检查点表
+CREATE TABLE `etl_checkpoint` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `checkpoint_id` VARCHAR(64) NOT NULL COMMENT '检查点ID',
+ `job_id` VARCHAR(64) NOT NULL COMMENT '任务ID',
+ `instance_id` VARCHAR(64) NOT NULL COMMENT '实例ID',
+ `checkpoint_type` VARCHAR(32) DEFAULT 'AUTO' COMMENT '检查点类型: AUTO/MANUAL',
+ `checkpoint_status` VARCHAR(32) NOT NULL COMMENT '状态: IN_PROGRESS/COMPLETED/FAILED',
+ `trigger_time` DATETIME NOT NULL COMMENT '触发时间',
+ `complete_time` DATETIME COMMENT '完成时间',
+ `duration_ms` BIGINT COMMENT '耗时(毫秒)',
+ `state_size_bytes` BIGINT COMMENT '状态大小(字节)',
+ `storage_path` VARCHAR(512) COMMENT '存储路径',
+ `state_snapshot` JSON COMMENT '状态快照(小状态直接存储)',
+ `error_message` TEXT COMMENT '错误信息',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_checkpoint_id` (`checkpoint_id`),
+ KEY `idx_job_id` (`job_id`),
+ KEY `idx_instance_id` (`instance_id`),
+ KEY `idx_trigger_time` (`trigger_time`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='检查点表';
+
+-- =============================================
+-- 5. 监控指标相关表(简化)
+-- =============================================
+
+-- 5.1 任务运行指标表
+CREATE TABLE `etl_job_metrics` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `job_id` VARCHAR(64) NOT NULL COMMENT '任务ID',
+ `instance_id` VARCHAR(64) NOT NULL COMMENT '实例ID',
+ `metric_time` DATETIME NOT NULL COMMENT '指标时间',
+ `records_read_total` BIGINT DEFAULT 0 COMMENT '累计读取记录数',
+ `records_processed_total` BIGINT DEFAULT 0 COMMENT '累计处理记录数',
+ `records_written_total` BIGINT DEFAULT 0 COMMENT '累计写入记录数',
+ `records_read_rate` DECIMAL(20,2) DEFAULT 0 COMMENT '读取速率(记录/秒)',
+ `records_write_rate` DECIMAL(20,2) DEFAULT 0 COMMENT '写入速率(记录/秒)',
+ `processing_latency_ms` BIGINT DEFAULT 0 COMMENT '处理延迟(毫秒)',
+ `backpressure_count` INT DEFAULT 0 COMMENT '背压次数',
+ `error_count` INT DEFAULT 0 COMMENT '错误次数',
+ `checkpoint_count` INT DEFAULT 0 COMMENT '检查点次数',
+ `restart_count` INT DEFAULT 0 COMMENT '重启次数',
+ `jvm_heap_used_mb` DECIMAL(10,2) COMMENT 'JVM堆内存使用(MB)',
+ `jvm_heap_max_mb` DECIMAL(10,2) COMMENT 'JVM堆内存最大(MB)',
+ `cpu_usage_percent` DECIMAL(5,2) COMMENT 'CPU使用率(%)',
+ `thread_count` INT COMMENT '线程数',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_job_id` (`job_id`),
+ KEY `idx_instance_id` (`instance_id`),
+ KEY `idx_metric_time` (`metric_time`),
+ KEY `idx_job_metric_time` (`job_id`, `metric_time`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='任务运行指标表';
+
+-- =============================================
+-- 6. 系统配置和告警相关表
+-- =============================================
+
+-- 6.1 系统配置表
+CREATE TABLE `etl_system_config` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `config_key` VARCHAR(128) NOT NULL COMMENT '配置Key',
+ `config_value` TEXT NOT NULL COMMENT '配置Value',
+ `config_type` VARCHAR(32) NOT NULL COMMENT '配置类型: STRING/INT/BOOLEAN/JSON',
+ `config_group` VARCHAR(64) COMMENT '配置分组: SYSTEM/EXECUTOR/CHECKPOINT/METRICS',
+ `description` TEXT COMMENT '描述',
+ `is_encrypted` TINYINT DEFAULT 0 COMMENT '是否加密: 0-否, 1-是',
+ `is_readonly` TINYINT DEFAULT 0 COMMENT '是否只读: 0-否, 1-是',
+ `updater` VARCHAR(64) COMMENT '更新人',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_config_key` (`config_key`),
+ KEY `idx_config_group` (`config_group`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统配置表';
+
+-- 6.2 告警规则表
+CREATE TABLE `etl_alert_rule` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `rule_id` VARCHAR(64) NOT NULL COMMENT '规则ID',
+ `rule_name` VARCHAR(128) NOT NULL COMMENT '规则名称',
+ `rule_type` VARCHAR(32) NOT NULL COMMENT '规则类型: JOB_FAILED/JOB_TIMEOUT/HIGH_ERROR_RATE/CHECKPOINT_FAILED',
+ `job_id` VARCHAR(64) COMMENT '目标任务ID(空表示所有任务)',
+ `condition_expression` TEXT COMMENT '条件表达式',
+ `alert_level` VARCHAR(32) NOT NULL DEFAULT 'WARNING' COMMENT '告警级别: INFO/WARNING/ERROR/CRITICAL',
+ `notification_channels` VARCHAR(256) COMMENT '通知渠道(逗号分隔): EMAIL/SMS/WEBHOOK/DINGTALK',
+ `notification_config` JSON COMMENT '通知配置(JSON)',
+ `is_enabled` TINYINT DEFAULT 1 COMMENT '是否启用: 0-否, 1-是',
+ `creator` VARCHAR(64) COMMENT '创建人',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_rule_id` (`rule_id`),
+ KEY `idx_rule_type` (`rule_type`),
+ KEY `idx_job_id` (`job_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='告警规则表';
+
+-- 6.3 告警记录表
+CREATE TABLE `etl_alert_record` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `alert_id` VARCHAR(64) NOT NULL COMMENT '告警ID',
+ `rule_id` VARCHAR(64) NOT NULL COMMENT '规则ID',
+ `rule_name` VARCHAR(128) NOT NULL COMMENT '规则名称',
+ `alert_level` VARCHAR(32) NOT NULL COMMENT '告警级别',
+ `job_id` VARCHAR(64) COMMENT '任务ID',
+ `instance_id` VARCHAR(64) COMMENT '实例ID',
+ `alert_time` DATETIME NOT NULL COMMENT '告警时间',
+ `alert_message` TEXT NOT NULL COMMENT '告警消息',
+ `alert_context` JSON COMMENT '告警上下文(JSON)',
+ `is_resolved` TINYINT DEFAULT 0 COMMENT '是否已解决: 0-否, 1-是',
+ `resolve_time` DATETIME COMMENT '解决时间',
+ `notification_status` VARCHAR(32) COMMENT '通知状态: PENDING/SENT/FAILED',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_alert_id` (`alert_id`),
+ KEY `idx_rule_id` (`rule_id`),
+ KEY `idx_job_id` (`job_id`),
+ KEY `idx_alert_time` (`alert_time`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='告警记录表';
+
+-- =============================================
+-- 7. 用户和审计相关表
+-- =============================================
+
+-- 7.1 用户表
+CREATE TABLE `etl_user` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `user_id` VARCHAR(64) NOT NULL COMMENT '用户ID',
+ `username` VARCHAR(64) NOT NULL COMMENT '用户名',
+ `password` VARCHAR(128) COMMENT '密码(加密)',
+ `email` VARCHAR(128) COMMENT '邮箱',
+ `phone` VARCHAR(32) COMMENT '手机号',
+ `real_name` VARCHAR(64) COMMENT '真实姓名',
+ `role` VARCHAR(32) DEFAULT 'USER' COMMENT '角色: ADMIN/USER',
+ `status` VARCHAR(32) DEFAULT 'ACTIVE' COMMENT '状态: ACTIVE/INACTIVE',
+ `last_login_time` DATETIME COMMENT '最后登录时间',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_user_id` (`user_id`),
+ UNIQUE KEY `uk_username` (`username`),
+ KEY `idx_email` (`email`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
+
+-- 7.2 操作日志表
+CREATE TABLE `etl_operation_log` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `log_id` VARCHAR(64) NOT NULL COMMENT '日志ID',
+ `user_id` VARCHAR(64) COMMENT '用户ID',
+ `username` VARCHAR(64) COMMENT '用户名',
+ `operation_type` VARCHAR(64) NOT NULL COMMENT '操作类型: CREATE/UPDATE/DELETE/START/STOP/RESTART',
+ `resource_type` VARCHAR(32) NOT NULL COMMENT '资源类型: JOB/DATASOURCE/SCHEDULE',
+ `resource_id` VARCHAR(64) COMMENT '资源ID',
+ `operation_desc` TEXT COMMENT '操作描述',
+ `request_params` JSON COMMENT '请求参数(JSON)',
+ `operation_status` VARCHAR(32) NOT NULL COMMENT '操作状态: SUCCESS/FAILED',
+ `error_message` TEXT COMMENT '错误信息',
+ `ip_address` VARCHAR(64) COMMENT 'IP地址',
+ `operation_time` DATETIME NOT NULL COMMENT '操作时间',
+ `duration_ms` BIGINT COMMENT '耗时(毫秒)',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_log_id` (`log_id`),
+ KEY `idx_user_id` (`user_id`),
+ KEY `idx_resource` (`resource_type`, `resource_id`),
+ KEY `idx_operation_time` (`operation_time`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作日志表';
+
+-- =============================================
+-- 初始化数据
+-- =============================================
+
+-- 插入内置连接器
+INSERT INTO `etl_connector` (`connector_id`, `connector_name`, `connector_type`, `connector_class`, `version`, `description`, `support_source`, `support_sink`, `is_builtin`, `is_enabled`, `creator`) VALUES
+('jdbc-connector', 'JDBC Connector', 'JDBC', 'com.etl.connector.jdbc.JdbcConnector', '1.0.0', 'JDBC数据库连接器,支持MySQL、PostgreSQL、Oracle等', 1, 1, 1, 1, 'system'),
+('kafka-connector', 'Kafka Connector', 'KAFKA', 'com.etl.connector.kafka.KafkaConnector', '1.0.0', 'Apache Kafka消息队列连接器', 1, 1, 1, 1, 'system'),
+('http-connector', 'HTTP Connector', 'HTTP', 'com.etl.connector.http.HttpConnector', '1.0.0', 'HTTP/HTTPS API连接器', 1, 1, 1, 1, 'system'),
+('file-connector', 'File Connector', 'FILE', 'com.etl.connector.file.FileConnector', '1.0.0', '文件系统连接器,支持CSV、JSON、Parquet等格式', 1, 1, 1, 1, 'system'),
+('redis-connector', 'Redis Connector', 'REDIS', 'com.etl.connector.redis.RedisConnector', '1.0.0', 'Redis缓存连接器', 1, 1, 1, 1, 'system'),
+('elasticsearch-connector', 'Elasticsearch Connector', 'ELASTICSEARCH', 'com.etl.connector.es.ElasticsearchConnector', '1.0.0', 'Elasticsearch搜索引擎连接器', 1, 1, 1, 1, 'system');
+
+-- 插入系统配置
+INSERT INTO `etl_system_config` (`config_key`, `config_value`, `config_type`, `config_group`, `description`) VALUES
+('system.thread.pool.core.size', '10', 'INT', 'EXECUTOR', '执行器线程池核心大小'),
+('system.thread.pool.max.size', '50', 'INT', 'EXECUTOR', '执行器线程池最大大小'),
+('system.thread.pool.queue.capacity', '1000', 'INT', 'EXECUTOR', '线程池队列容量'),
+('system.checkpoint.enabled', 'true', 'BOOLEAN', 'CHECKPOINT', '全局是否启用检查点'),
+('system.checkpoint.interval.seconds', '60', 'INT', 'CHECKPOINT', '默认检查点间隔(秒)'),
+('system.checkpoint.storage.path', '/data/checkpoints', 'STRING', 'CHECKPOINT', '检查点存储路径'),
+('system.checkpoint.retention.count', '5', 'INT', 'CHECKPOINT', '保留检查点数量'),
+('system.metrics.enabled', 'true', 'BOOLEAN', 'METRICS', '是否启用监控指标采集'),
+('system.metrics.collect.interval.seconds', '10', 'INT', 'METRICS', '指标采集间隔(秒)'),
+('system.scheduler.enabled', 'true', 'BOOLEAN', 'SYSTEM', '是否启用调度器'),
+('system.restart.max.attempts', '3', 'INT', 'EXECUTOR', '默认最大重启次数');
+
+-- 插入默认告警规则
+INSERT INTO `etl_alert_rule` (`rule_id`, `rule_name`, `rule_type`, `alert_level`, `condition_expression`, `is_enabled`, `creator`) VALUES
+('alert-job-failed', '任务失败告警', 'JOB_FAILED', 'ERROR', 'instance_status == FAILED', 1, 'system'),
+('alert-job-timeout', '任务超时告警', 'JOB_TIMEOUT', 'WARNING', 'duration_ms > 3600000', 1, 'system'),
+('alert-high-error-rate', '高错误率告警', 'HIGH_ERROR_RATE', 'WARNING', 'error_count / records_read_total > 0.01', 1, 'system'),
+('alert-checkpoint-failed', '检查点失败告警', 'CHECKPOINT_FAILED', 'WARNING', 'checkpoint_status == FAILED', 1, 'system');
+
+-- 插入默认管理员用户(密码: admin123,需要BCrypt加密)
+INSERT INTO `etl_user` (`user_id`, `username`, `password`, `email`, `real_name`, `role`, `status`) VALUES
+('user-admin', 'admin', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iKTVKIUi', 'admin@example.com', '系统管理员', 'ADMIN', 'ACTIVE');
+
+-- =============================================
+-- 视图定义(方便查询)
+-- =============================================
+
+-- 任务实例统计视图
+CREATE OR REPLACE VIEW `v_job_instance_stats` AS
+SELECT
+ j.job_id,
+ j.job_name,
+ j.job_type,
+ j.job_status,
+ COUNT(i.id) as total_runs,
+ SUM(CASE WHEN i.instance_status = 'COMPLETED' THEN 1 ELSE 0 END) as success_runs,
+ SUM(CASE WHEN i.instance_status = 'FAILED' THEN 1 ELSE 0 END) as failed_runs,
+ AVG(i.duration_ms) as avg_duration_ms,
+ MAX(i.start_time) as last_run_time
+FROM etl_job j
+LEFT JOIN etl_job_instance i ON j.job_id = i.job_id
+WHERE j.is_deleted = 0
+GROUP BY j.job_id, j.job_name, j.job_type, j.job_status;
+
+-- 当前运行任务视图
+CREATE OR REPLACE VIEW `v_running_jobs` AS
+SELECT
+ i.instance_id,
+ i.job_id,
+ i.job_name,
+ i.instance_status,
+ i.host_address,
+ i.start_time,
+ TIMESTAMPDIFF(SECOND, i.start_time, NOW()) as running_seconds,
+ i.records_read,
+ i.records_processed,
+ i.records_written
+FROM etl_job_instance i
+WHERE i.instance_status = 'RUNNING'
+ORDER BY i.start_time DESC;
+
+-- =============================================
+-- 索引优化建议(根据实际查询调整)
+-- =============================================
+-- ALTER TABLE `etl_job_instance` ADD INDEX `idx_job_status_time` (`job_id`, `instance_status`, `start_time`);
+-- ALTER TABLE `etl_job_metrics` ADD INDEX `idx_instance_metric_time` (`instance_id`, `metric_time`);
+
+-- =============================================
+-- 分区建议(数据量大时)
+-- =============================================
+-- ALTER TABLE `etl_job_metrics` PARTITION BY RANGE (TO_DAYS(metric_time)) (
+-- PARTITION p202501 VALUES LESS THAN (TO_DAYS('2025-02-01')),
+-- PARTITION p202502 VALUES LESS THAN (TO_DAYS('2025-03-01')),
+-- PARTITION p_future VALUES LESS THAN MAXVALUE
+-- );
diff --git a/docs/enterprise-cdp-design.md b/docs/enterprise-cdp-design.md
new file mode 100644
index 000000000..3f18eb5b4
--- /dev/null
+++ b/docs/enterprise-cdp-design.md
@@ -0,0 +1,1499 @@
+# 企业级CDP(客户数据平台)设计方案
+
+## 目录
+
+- [一、方案概述](#一方案概述)
+ - [1.1 背景与目标](#11-背景与目标)
+ - [1.2 核心能力](#12-核心能力)
+- [二、整体架构设计](#二整体架构设计)
+ - [2.1 架构分层](#21-架构分层)
+ - [2.2 核心数据流](#22-核心数据流)
+- [三、数据采集平台](#三数据采集平台)
+ - [3.1 数据源接入](#31-数据源接入)
+ - [3.1.1 CRM系统接入](#311-crm系统接入)
+ - [3.1.2 企业微信接入](#312-企业微信接入)
+ - [3.1.3 第三方数据接入](#313-第三方数据接入)
+ - [3.2 数据采集架构](#32-数据采集架构)
+ - [3.3 数据采集SDK设计](#33-数据采集sdk设计)
+- [四、OneID服务(统一身份识别)](#四oneid服务统一身份识别)
+ - [4.1 核心挑战](#41-核心挑战)
+ - [4.2 ID-Mapping策略](#42-id-mapping策略)
+ - [4.2.1 匹配规则](#421-匹配规则)
+ - [4.2.2 匹配算法流程](#422-匹配算法流程)
+ - [4.3 OneID数据模型](#43-oneid数据模型)
+ - [4.4 OneID服务能力](#44-oneid服务能力)
+- [五、组织架构模型设计](#五组织架构模型设计)
+ - [5.1 数据模型](#51-数据模型)
+ - [5.1.1 客户企业层级模型](#511-客户企业层级模型)
+ - [5.1.2 联系人组织关系模型](#512-联系人组织关系模型)
+ - [5.2 组织关系查询能力](#52-组织关系查询能力)
+ - [5.2.1 核心查询场景](#521-核心查询场景)
+ - [5.2.2 图数据库优化](#522-图数据库优化)
+ - [5.3 组织架构可视化](#53-组织架构可视化)
+- [六、数据建模与存储](#六数据建模与存储)
+ - [6.1 数据分层架构](#61-数据分层架构)
+ - [6.2 核心数据模型](#62-核心数据模型)
+ - [6.2.1 客户企业主题](#621-客户企业主题)
+ - [6.2.2 联系人主题](#622-联系人主题)
+ - [6.2.3 行为事件主题](#623-行为事件主题)
+ - [6.3 存储选型](#63-存储选型)
+- [七、标签体系设计](#七标签体系设计)
+ - [7.1 标签分类](#71-标签分类)
+ - [7.1.1 客户企业标签](#711-客户企业标签)
+ - [7.1.2 联系人标签](#712-联系人标签)
+ - [7.1.3 组织关系标签](#713-组织关系标签)
+ - [7.2 标签计算引擎](#72-标签计算引擎)
+ - [7.2.1 标签类型](#721-标签类型)
+ - [7.2.2 标签计算流程](#722-标签计算流程)
+ - [7.3 标签存储方案](#73-标签存储方案)
+- [八、圈人能力设计](#八圈人能力设计)
+ - [8.1 圈人场景](#81-圈人场景)
+ - [8.2 圈人条件](#82-圈人条件)
+ - [8.2.1 基础条件](#821-基础条件)
+ - [8.2.2 组织关系条件](#822-组织关系条件)
+ - [8.3 圈人引擎](#83-圈人引擎)
+ - [8.3.1 查询优化](#831-查询优化)
+ - [8.3.2 圈人服务能力](#832-圈人服务能力)
+ - [8.4 圈人结果应用](#84-圈人结果应用)
+- [九、数据安全与合规](#九数据安全与合规)
+ - [9.1 合规要求](#91-合规要求)
+ - [9.2 数据脱敏策略](#92-数据脱敏策略)
+ - [9.2.1 脱敏字段](#921-脱敏字段)
+ - [9.2.2 加密存储](#922-加密存储)
+ - [9.3 权限控制](#93-权限控制)
+ - [9.3.1 RBAC模型](#931-rbac模型)
+ - [9.3.2 数据权限](#932-数据权限)
+ - [9.4 审计日志](#94-审计日志)
+- [十、技术选型与架构](#十技术选型与架构)
+ - [10.1 技术栈选型](#101-技术栈选型)
+ - [10.1.1 后端技术栈](#1011-后端技术栈)
+ - [10.1.2 前端技术栈](#1012-前端技术栈)
+ - [10.2 部署架构](#102-部署架构)
+ - [10.2.1 云上部署(推荐)](#1021-云上部署推荐)
+ - [10.2.2 私有化部署](#1022-私有化部署)
+ - [10.3 核心服务设计](#103-核心服务设计)
+ - [10.3.1 服务拆分](#1031-服务拆分)
+ - [10.3.2 服务通信](#1032-服务通信)
+- [十一、系统实施路线图](#十一系统实施路线图)
+ - [11.1 Phase 1: MVP版本 (2-3个月)](#111-phase-1-mvp版本-2-3个月)
+ - [11.2 Phase 2: 增强版本 (3-4个月)](#112-phase-2-增强版本-3-4个月)
+ - [11.3 Phase 3: 智能版本 (4-6个月)](#113-phase-3-智能版本-4-6个月)
+- [十二、成功案例参考](#十二成功案例参考)
+ - [12.1 客户画像场景](#121-客户画像场景)
+ - [12.2 组织穿透场景](#122-组织穿透场景)
+ - [12.3 精准营销场景](#123-精准营销场景)
+- [十三、总结与展望](#十三总结与展望)
+ - [13.1 企业级CDP与C端CDP的核心差异](#131-企业级cdp与c端cdp的核心差异)
+ - [13.2 关键成功要素](#132-关键成功要素)
+ - [13.3 未来演进方向](#133-未来演进方向)
+- [附录](#附录)
+ - [附录A:关键指标定义](#附录a关键指标定义)
+ - [附录B:核心服务接口](#附录b核心服务接口)
+
+---
+
+## 一、方案概述
+
+[返回目录](#目录)
+
+### 1.1 背景与目标
+
+本方案针对B2B场景下的企业级客户数据平台(CDP),核心特点是:
+- **客户主体是企业**:不同于C端CDP,需要管理企业客户及其内部联系人
+- **组织架构关系**:支持企业客户的组织架构管理,可追溯上下级、同事等关系
+- **销售场景驱动**:销售人员通过企业微信等渠道与客户互动,需要完整的客户画像支持
+
+### 1.2 核心能力
+
+- **全渠道数据采集**:整合CRM、企业微信、第三方数据等多源数据
+- **OneID统一身份**:打通多渠道的客户身份,形成360度客户视图
+- **组织架构管理**:支持企业客户的组织层级关系,快速定位关键决策人
+- **智能标签体系**:基于行为、属性、组织关系的多维标签
+- **精准圈人能力**:支持基于标签、组织关系的客户筛选
+- **数据安全合规**:符合个人信息保护法、数据安全法等监管要求
+
+---
+
+## 二、整体架构设计
+
+[返回目录](#目录)
+
+### 2.1 架构分层
+
+整体架构采用经典的五层架构模式,从下至上分别为:数据采集层、数据存储层、数据处理层、服务层、应用层。
+
+```mermaid
+graph TB
+ subgraph 应用层
+ A1[销售工作台]
+ A2[营销平台]
+ A3[BI分析]
+ A4[API网关]
+ end
+
+ subgraph 服务层
+ S1[圈人服务]
+ S2[标签服务]
+ S3[画像服务]
+ S4[组织服务]
+ S5[OneID服务]
+ S6[埋点服务]
+ S7[数据质量]
+ S8[权限服务]
+ end
+
+ subgraph 数据处理层
+ P1[实时计算-Flink]
+ P2[离线计算-Spark]
+ P3[标签计算]
+ P4[数据清洗]
+ end
+
+ subgraph 数据存储层
+ D1[MySQL-元数据]
+ D2[ES-搜索]
+ D3[HBase-宽表]
+ D4[Redis-缓存]
+ D5[Hive-数据湖]
+ D6[ClickHouse-OLAP]
+ D7[Neo4j-图数据库]
+ end
+
+ subgraph 数据采集层
+ C1[CRM数据同步]
+ C2[企业微信事件采集]
+ C3[第三方数据接入]
+ C4[行为埋点SDK]
+ end
+
+ 应用层 --> 服务层
+ 服务层 --> 数据处理层
+ 数据处理层 --> 数据存储层
+ 数据存储层 --> 数据采集层
+```
+
+### 2.2 核心数据流
+
+系统的核心数据流转包括以下四个主要流程:
+
+1. **数据采集流程**:CRM/企微/第三方 → 消息队列(Kafka) → 数据清洗 → 存储
+2. **OneID流程**:多源数据 → ID-Mapping → 统一客户视图
+3. **标签计算流程**:原始数据 → 规则引擎 → 标签生成 → 标签存储
+4. **圈人查询流程**:条件输入 → 查询引擎 → 结果集 → 导出/推送
+
+---
+
+## 三、数据采集平台
+
+[返回目录](#目录)
+
+### 3.1 数据源接入
+
+#### 3.1.1 CRM系统接入
+
+**接入方式**:
+- **全量同步**:定时任务(如每日凌晨),同步客户主数据、联系人、商机等
+- **增量同步**:实时或准实时(5-15分钟),基于时间戳或CDC(Change Data Capture)
+- **API接口**:提供双向API,支持CRM系统实时推送数据变更
+
+**数据内容**:
+- **客户企业信息**:企业名称、行业、规模、年营收、地址、成立时间等
+- **联系人信息**:姓名、职位、部门、手机、邮箱、汇报关系等
+- **商机信息**:商机阶段、金额、预计成交时间、负责销售等
+- **活动记录**:拜访记录、通话记录、邮件往来等
+
+#### 3.1.2 企业微信接入
+
+**接入方式**:
+- **企微API对接**:基于企业微信官方API,获取通讯录、客户、聊天记录等
+- **事件订阅**:订阅企微事件(添加客户、聊天、标签变更等),实时推送
+- **侧边栏应用**:在企微侧边栏嵌入CDP能力,销售可直接查看客户画像
+
+**采集数据类型**:
+- **通讯录数据**:企业组织架构、员工信息
+- **客户数据**:外部联系人、添加时间、添加来源
+- **互动数据**:聊天记录(需客户授权)、会话次数、回复时长
+- **群聊数据**:客户群信息、群成员、群消息
+- **雷达数据**:客户浏览行为(如浏览官网链接、产品手册)
+
+**数据示例**:
+企业微信事件数据通常包含事件类型(如添加外部联系人)、事件时间、员工信息、外部联系人信息、添加方式、来源渠道等维度信息。
+
+#### 3.1.3 第三方数据接入
+
+**数据类型**:
+- **企业征信数据**:企查查、天眼查等,企业工商信息、风险信息
+- **行业数据**:行业报告、竞品信息
+- **公开数据**:企业官网、招聘信息、新闻舆情
+
+**接入方式**:
+- **API调用**:定时或触发式调用第三方API
+- **文件导入**:Excel/CSV批量导入
+- **爬虫采集**:合规前提下的数据抓取
+
+### 3.2 数据采集架构
+
+数据采集架构采用分层设计,确保数据从源系统到存储层的可靠传输和处理。
+
+```mermaid
+graph TB
+ subgraph 数据源层
+ DS1[CRM系统]
+ DS2[企业微信]
+ DS3[第三方API]
+ DS4[行为埋点]
+ end
+
+ subgraph 数据采集网关
+ GW1[CRM Connector]
+ GW2[企微 Connector]
+ GW3[API Gateway]
+ GW4[SDK Collector]
+ end
+
+ subgraph 消息队列
+ MQ[Kafka Topics
crm-data | wework-event | 3rd-data | track]
+ end
+
+ subgraph 数据预处理层
+ FL[Flink Stream Processing
- 数据格式标准化
- 数据清洗去重
- 数据脱敏
- 数据校验]
+ end
+
+ subgraph 数据落地层
+ DL[ODS原始数据 → DWD明细数据 → DWS汇总数据]
+ end
+
+ DS1 --> GW1
+ DS2 --> GW2
+ DS3 --> GW3
+ DS4 --> GW4
+ GW1 --> MQ
+ GW2 --> MQ
+ GW3 --> MQ
+ GW4 --> MQ
+ MQ --> FL
+ FL --> DL
+```
+
+**架构说明**:
+
+1. **数据采集网关**:负责数据格式转换、协议适配、限流熔断
+2. **消息队列Kafka**:作为数据缓冲层,支持高吞吐量的数据接入
+3. **数据预处理Flink**:实时流处理,完成数据标准化、清洗、脱敏、校验
+4. **数据落地**:按照数仓分层架构存储到不同层级
+
+### 3.3 数据采集SDK设计
+
+对于官网、营销页面等场景,提供JavaScript埋点SDK,支持以下核心能力:
+
+**SDK核心功能**:
+- **初始化配置**:配置AppKey、服务端URL、自动埋点开关
+- **用户识别**:识别用户身份(userId、accountId)和基本属性
+- **事件追踪**:追踪页面浏览、按钮点击、表单提交等行为事件
+- **企业信息追踪**:追踪企业级别的属性信息
+
+**SDK设计要点**:
+- 采用异步上报,不阻塞页面渲染
+- 本地缓冲队列,批量上报提升性能
+- 断点续传,网络异常时自动重试
+- 数据加密传输,保障安全性
+
+---
+
+## 四、OneID服务(统一身份识别)
+
+[返回目录](#目录)
+
+### 4.1 核心挑战
+
+在企业级CDP中,同一个联系人可能在多个系统中有不同的标识:
+- CRM中有联系人ID
+- 企业微信中有external_user_id
+- 官网浏览时通过cookie识别
+- 第三方数据中通过手机号或邮箱标识
+
+**OneID的目标**:将这些碎片化的身份统一为唯一的CDP ID,构建完整客户视图。
+
+### 4.2 ID-Mapping策略
+
+#### 4.2.1 匹配规则
+
+**强匹配规则**(优先级从高到低):
+1. **手机号**:中国手机号唯一性强,作为首要匹配字段
+2. **邮箱**:企业邮箱唯一性较强
+3. **证件号**:如身份证(需脱敏处理)
+4. **企业微信unionid**:跨应用唯一标识
+
+**弱匹配规则**:
+- 姓名 + 公司名称
+- 姓名 + 部门 + 职位
+- 设备ID(移动端)
+
+#### 4.2.2 匹配算法流程
+
+OneID匹配采用基于规则的算法流程:
+
+```mermaid
+graph TD
+ A[新数据进入] --> B[提取匹配字段
手机/邮箱/unionid]
+ B --> C{查询ID-Mapping表
是否已存在匹配?}
+ C -->|存在| D[使用已有CDP ID
更新source映射关系]
+ C -->|不存在| E[生成新CDP ID
创建映射记录]
+ D --> F{是否有冲突?
一个source_id对应多个CDP ID}
+ F -->|有冲突| G[触发人工审核
或自动合并策略]
+ F -->|无冲突| H[完成匹配]
+ E --> H
+ G --> H
+```
+
+**ID-Mapping表设计要点**:
+- 记录CDP统一ID与各来源系统ID的映射关系
+- 记录匹配字段(mobile/email/unionid)和匹配值
+- 记录匹配置信度(0.00-1.00)
+- 支持按来源类型、来源ID、匹配字段索引查询
+
+### 4.3 OneID数据模型
+
+#### 统一客户视图
+
+统一客户视图整合了来自多个数据源的客户信息,形成360度客户画像:
+
+**客户企业信息**:
+- 基本信息:企业ID、企业名称、行业、规模、状态等
+- 经营信息:年营收、融资轮次、成立时间等
+
+**联系人信息**:
+- 基本信息:姓名、职位、部门、职级等
+- 联系方式:手机号(脱敏)、邮箱(脱敏)
+- 决策角色:决策者、影响者、使用者等
+
+**组织关系**:
+- 汇报关系:直属上级CDP ID、上级姓名
+- 下属关系:直接下属列表
+- 组织路径:部门层级路径
+
+**来源系统ID映射**:
+- CRM联系人ID
+- 企业微信external_user_id
+- 第三方系统ID
+
+**客户标签**:
+- 行为标签、属性标签、预测标签等
+
+**活跃信息**:
+- 最后活跃时间、创建时间等
+
+### 4.4 OneID服务能力
+
+OneID服务对外提供以下核心能力:
+
+**服务接口清单**:
+
+1. **根据来源ID获取CDP ID**:输入来源系统类型和来源ID,返回统一的CDP ID
+2. **ID绑定/合并**:将新的来源ID与已有CDP ID进行绑定
+3. **获取统一客户视图**:根据CDP ID获取完整的客户360度视图
+4. **ID合并**:当发现多个CDP ID实际是同一人时,执行ID合并操作
+
+**服务调用方式**:
+- REST API:同步调用,适用于实时查询场景
+- Kafka消息:异步调用,适用于批量ID绑定场景
+
+---
+
+## 五、组织架构模型设计
+
+[返回目录](#目录)
+
+### 5.1 数据模型
+
+企业级CDP的核心特色在于**组织架构关系**,需要建立两层模型:
+
+#### 5.1.1 客户企业层级模型
+
+**客户企业表**:
+- 存储客户企业基本信息
+- 支持集团型企业的母子公司关系(parent_account_id)
+- 区分企业层级:集团、子公司、分公司
+- 记录企业所属行业、规模、年营收等关键属性
+- 记录客户状态:潜在客户、商机、成交客户、流失
+- 记录客户负责人(owner_staff_id)
+
+**客户企业组织架构表**:
+- 存储客户企业内部的组织架构信息
+- 支持多级组织结构(parent_org_id)
+- 记录组织类型:部门、中心、小组等
+- 记录组织路径(如:/某公司/技术部/研发中心)
+- 记录组织负责人的CDP ID
+
+#### 5.1.2 联系人组织关系模型
+
+**联系人主表**:
+- 存储联系人基本信息:姓名、职位、职级、资历等
+- 敏感信息加密存储:手机号、邮箱
+- 关联所属客户企业(account_id)
+- 记录职级:员工/主管/经理/总监/VP/CXO
+- 记录资历:初级/中级/高级/专家
+
+**联系人组织关系表**:
+- 存储联系人与组织的关联关系
+- 支持一个人在多个组织中(兼职、虚线汇报)
+- 记录直属上级(report_to_cdp_id)
+- 区分主要职位和兼职
+- 记录岗位类型:正式、兼职、虚线汇报
+- 支持时间有效性(start_date、end_date)
+
+### 5.2 组织关系查询能力
+
+基于上述模型,提供强大的组织关系查询能力:
+
+#### 5.2.1 核心查询场景
+
+组织服务对外提供以下核心查询能力:
+
+**向上查询**:
+- **查询直属上级**:查询某人的直接汇报上级
+- **查询所有上级**:向上递归查询到CEO/总经理
+
+**向下查询**:
+- **查询直属下属**:查询某人的直接下属
+- **查询所有下属**:向下递归查询所有层级的下属
+
+**平级查询**:
+- **查询部门成员**:查询某个部门的所有成员
+- **支持级联查询**:可选择是否包含子部门
+
+**关系查询**:
+- **查询共同上级**:找到两个人的最近共同上级(LCA算法)
+- **查询决策链**:找到某个部门的决策层人员
+
+#### 5.2.2 图数据库优化
+
+对于复杂的组织关系查询,建议使用**Neo4j图数据库**进行优化:
+
+**图数据库优势**:
+- 天然适合处理关系数据
+- 支持多层级递归查询
+- 查询性能优于关系型数据库(尤其是深层递归)
+- 支持复杂的路径查询和图算法
+
+**节点设计**:
+- **联系人节点(Contact)**:存储联系人基本信息
+- **组织节点(Organization)**:存储部门/团队信息
+
+**关系设计**:
+- **汇报关系(REPORT_TO)**:建立上下级关系
+- **所属关系(BELONG_TO)**:建立联系人与部门的关系
+
+**典型查询场景**:
+- 向上追溯所有上级
+- 向下追溯所有下属
+- 查询两人的共同上级(最短路径)
+- 查询某人的同事(共同上级的下属)
+
+### 5.3 组织架构可视化
+
+在销售工作台中,提供组织架构图可视化能力,帮助销售快速了解客户企业的组织结构。
+
+**组织架构图示例**:
+
+```mermaid
+graph TD
+ CEO[CEO - 王总
已触达]
+
+ CEO --> VP_TECH[技术VP - 李总
未触达]
+ CEO --> VP_SALES[销售VP - 刘总
已触达]
+
+ VP_TECH --> DIR_TECH[技术总监 - 张三
已触达]
+ VP_TECH --> DIR_PROD[产品总监 - 周六
未触达]
+
+ VP_SALES --> DIR_KEY[大客户总监 - 赵七
已触达]
+ VP_SALES --> DIR_CHANNEL[渠道总监 - 孙八
未触达]
+
+ style CEO fill:#90EE90
+ style VP_SALES fill:#90EE90
+ style DIR_TECH fill:#90EE90
+ style DIR_KEY fill:#90EE90
+ style VP_TECH fill:#FFB6C1
+ style DIR_PROD fill:#FFB6C1
+ style DIR_CHANNEL fill:#FFB6C1
+```
+
+**可视化功能要点**:
+
+1. **节点信息展示**:
+ - 姓名、职位、部门
+ - 联系方式(有权限时显示)
+ - 标签信息(如"决策者"、"高意向")
+
+2. **触达状态标识**:
+ - 已触达:绿色节点
+ - 未触达:红色节点
+ - 触达方式:企微、邮件、电话等
+
+3. **交互功能**:
+ - 点击节点查看详细画像
+ - 展开/收起子节点
+ - 高亮显示某条汇报链路
+ - 导出组织架构图
+
+4. **前端技术选型**:
+ - **图可视化库**:AntV G6、D3.js、Cytoscape.js
+ - **布局算法**:树形布局、层次布局
+ - **响应式设计**:支持大屏展示和移动端
+
+---
+
+## 六、数据建模与存储
+
+[返回目录](#目录)
+
+### 6.1 数据分层架构
+
+采用标准的数仓分层架构,确保数据质量和查询性能:
+
+```mermaid
+graph LR
+ ODS[ODS
Operational Data Store
原始数据层] --> DWD[DWD
Data Warehouse Detail
明细数据层]
+ DWD --> DWS[DWS
Data Warehouse Summary
汇总数据层]
+ DWS --> ADS[ADS
Application Data Service
应用数据层]
+```
+
+**各层职责说明**:
+
+| 数据层 | 说明 | 数据处理 | 存储周期 |
+|-------|------|---------|---------|
+| **ODS** | 原始数据层 | 数据直接从源系统同步,保持原始格式 | 30-90天 |
+| **DWD** | 明细数据层 | 数据清洗、标准化、关联OneID | 1-2年 |
+| **DWS** | 汇总数据层 | 按天/周/月汇总统计 | 2-3年 |
+| **ADS** | 应用数据层 | 面向具体业务场景的宽表 | 长期保存 |
+
+### 6.2 核心数据模型
+
+#### 6.2.1 客户企业主题
+
+**DWD: 客户企业明细表**
+
+存储客户企业的明细信息,包括:
+- 企业基本信息:企业ID、企业名称、行业、规模、年营收
+- 客户状态:潜在客户、商机、成交客户、流失
+- 负责人信息:客户负责人(销售)
+- 时间信息:首次接触日期、最近接触日期
+- 业务指标:商机总数、营收总额
+- 扩展字段:JSON格式存储灵活的扩展属性
+
+**DWS: 客户企业汇总表**
+
+按天统计客户企业的行为汇总数据:
+- 联系人数量
+- 互动次数(总计、企微聊天、邮件、会议)
+- 商机数量和金额
+- 活跃度指标(近7天活跃天数、近30天活跃天数)
+
+#### 6.2.2 联系人主题
+
+**DWD: 联系人明细表**
+
+存储联系人的明细信息:
+- 基本信息:CDP ID、姓名、职位、部门、职级
+- 组织关系:所属企业、直属上级
+- 敏感信息:手机号(加密)、邮箱(加密)
+- 来源系统ID:企业微信external_id等
+- 时间信息:首次添加时间、最后活跃时间
+
+**DWS: 联系人行为汇总表**
+
+按天统计联系人的行为汇总数据:
+- 浏览行为:页面浏览次数
+- 互动行为:企微聊天次数、回复次数、平均回复时长
+- 邮件行为:邮件打开次数、点击次数
+- 会议行为:会议参与次数
+- 文档行为:文档查看次数
+- 总互动次数和最后互动时间
+
+#### 6.2.3 行为事件主题
+
+**DWD: 行为事件明细表**
+
+存储用户的所有行为事件明细:
+- 事件基本信息:事件ID、事件类型、事件时间
+- 事件主体:联系人CDP ID、客户企业ID
+- 事件属性:JSON格式存储事件的详细属性
+- 数据来源:WEWORK/CRM/WEB等
+- 支持按日期分区,便于历史数据归档
+
+**常见事件类型**:
+- page_view:页面浏览
+- wework_chat:企微聊天
+- email_open:邮件打开
+- email_click:邮件点击
+- meeting_attend:会议参加
+- document_view:文档查看
+- form_submit:表单提交
+
+### 6.3 存储选型
+
+根据不同数据特点和访问模式,选择合适的存储方案:
+
+| 数据类型 | 存储方案 | 说明 | 典型应用场景 |
+|---------|---------|------|-------------|
+| **元数据** | MySQL | 账户信息、联系人信息、标签配置等 | 事务性查询、配置管理 |
+| **行为事件** | ClickHouse | 海量事件数据,支持OLAP分析 | 用户行为分析、漏斗分析 |
+| **实时画像** | HBase/Redis | 宽表存储,支持快速查询 | 客户360视图、实时标签查询 |
+| **组织关系** | Neo4j | 图数据库,支持复杂关系查询 | 组织架构查询、关系路径分析 |
+| **搜索** | Elasticsearch | 联系人搜索、企业搜索 | 全文检索、模糊搜索、聚合统计 |
+| **数据湖** | Hive/Iceberg | 原始数据长期存储 | 历史数据归档、数据回溯 |
+| **缓存** | Redis | 热点数据缓存,提升查询性能 | 高频访问数据、会话数据 |
+
+**存储选型原则**:
+- **元数据用MySQL**:事务性强、数据量小、需要ACID保证
+- **行为数据用ClickHouse**:写多读少、列式存储、支持OLAP分析
+- **实时数据用Redis/HBase**:读多写多、低延迟、高并发
+- **关系数据用Neo4j**:复杂关系查询、图算法、路径分析
+- **搜索用ES**:全文检索、模糊匹配、聚合统计
+- **冷数据用Hive/Iceberg**:长期归档、成本优化、支持数据湖
+
+---
+
+## 七、标签体系设计
+
+[返回目录](#目录)
+
+### 7.1 标签分类
+
+企业级CDP的标签体系分为三大类:
+
+#### 7.1.1 客户企业标签
+
+| 类别 | 标签示例 |
+|-----|---------|
+| **基础属性** | 行业、规模、地域、上市状态、成立时间 |
+| **商业属性** | 年营收、融资轮次、客户生命周期阶段 |
+| **业务状态** | 潜在客户、商机阶段、成交客户、流失客户 |
+| **行为特征** | 活跃度、互动频次、决策周期 |
+| **意向度** | 高意向、中意向、低意向、无意向 |
+| **产品偏好** | 关注AI产品、关注SaaS产品、关注定制化服务 |
+
+#### 7.1.2 联系人标签
+
+| 类别 | 标签示例 |
+|-----|---------|
+| **基础属性** | 姓名、职位、部门、职级、工作年限 |
+| **决策角色** | 决策者、影响者、使用者、把关者 |
+| **组织关系** | 部门负责人、核心团队成员、关键决策人 |
+| **行为特征** | 活跃用户、沉默用户、高频互动、快速回复 |
+| **兴趣偏好** | 关注技术细节、关注价格、关注案例、关注服务 |
+| **互动渠道** | 企微活跃、邮件活跃、会议活跃 |
+
+#### 7.1.3 组织关系标签
+
+| 类别 | 标签示例 |
+|-----|---------|
+| **层级标签** | 高层领导、中层管理、基层员工 |
+| **影响力标签** | 核心决策人、部门话事人、意见领袖 |
+| **关系标签** | 已触达高层、已触达决策人、仅触达执行层 |
+| **团队标签** | 完整决策链、缺失决策人、单点联系 |
+
+### 7.2 标签计算引擎
+
+#### 7.2.1 标签类型
+
+标签按照计算方式分为三大类:
+
+**1. 规则类标签**(基于条件判断)
+
+通过SQL规则定义标签计算逻辑,适用于明确的业务规则场景。
+
+**示例**:高意向客户
+- **规则定义**:近30天互动次数>=10次 AND 近7天有高层互动
+- **计算方式**:从DWS汇总表中查询符合条件的联系人
+- **更新频率**:每日计算
+
+**2. 统计类标签**(基于聚合计算)
+
+通过统计聚合计算得出的标签,适用于需要汇总统计的场景。
+
+**示例**:互动频次标签
+- **L7D_互动次数**:近7天的总互动次数
+- **L30D_互动次数**:近30天的总互动次数
+- **计算方式**:从行为汇总表中按时间范围聚合
+- **更新频率**:每日计算
+
+**3. 预测类标签**(基于机器学习模型)
+
+通过机器学习模型预测得出的标签,适用于复杂的预测场景。
+
+**示例**:成交概率预测
+- **特征工程**:
+ - 近30天互动次数
+ - 决策人触达数量
+ - 是否触达CXO
+ - 回复响应率
+ - 会议参与次数
+ - 文档查看次数
+- **模型算法**:随机森林、GBDT、神经网络等
+- **输出结果**:成交概率分数(0-1)
+- **更新频率**:每周/每月重新训练模型
+
+#### 7.2.2 标签计算流程
+
+标签计算采用统一的流程框架:
+
+```mermaid
+graph LR
+ A[标签定义
业务人员在平台配置规则] --> B[标签调度
定时任务触发计算]
+ B --> C[数据准备
从DWS层读取汇总数据]
+ C --> D[规则执行
执行SQL/Python脚本]
+ D --> E[结果写入
写入标签结果表]
+ E --> F[缓存更新
更新Redis缓存]
+```
+
+**流程说明**:
+
+1. **标签定义**:业务人员在标签管理平台配置标签规则
+2. **标签调度**:通过DolphinScheduler等调度工具,按照设定的频率(每日/每小时/实时)触发计算
+3. **数据准备**:从DWS汇总层读取所需的数据
+4. **规则执行**:根据标签类型,执行对应的计算逻辑(SQL查询、Python脚本、ML模型推理)
+5. **结果写入**:将计算结果写入标签结果表(MySQL)
+6. **缓存更新**:将热点标签数据更新到Redis,供实时查询使用
+
+### 7.3 标签存储方案
+
+标签系统需要两张核心表:
+
+**标签配置表**:
+- 存储标签的元数据信息
+- 字段包括:标签ID、标签名称、标签分类、标签类型(RULE/STAT/ML)
+- 记录目标类型:ACCOUNT(企业)/CONTACT(联系人)
+- 记录计算逻辑:SQL语句或规则描述
+- 记录计算频率:DAILY/HOURLY/REALTIME
+- 记录标签状态:是否启用
+
+**标签结果表**:
+- 存储标签的计算结果
+- 字段包括:目标ID(account_id或cdp_id)、目标类型、标签ID、标签值
+- 记录置信度:仅预测类标签需要(0.00-1.00)
+- 记录有效期:start_time、end_time
+- 支持标签的时效性管理
+- 按目标ID和标签ID建立联合主键
+
+**查询优化**:
+- 为标签结果表建立覆盖索引:(target_id, tag_id)
+- 热点标签数据缓存到Redis,key格式:`tag:result:{target_id}`
+- 支持批量查询某个客户的所有标签
+
+---
+
+## 八、圈人能力设计
+
+[返回目录](#目录)
+
+### 8.1 圈人场景
+
+基于标签和组织关系的客户筛选,典型场景:
+
+1. **精准营销**:圈选高意向的决策人,推送产品方案
+2. **销售分配**:圈选新增商机客户,分配给销售跟进
+3. **客户关怀**:圈选长期未互动的老客户,进行激活
+4. **交叉销售**:圈选已购买A产品的客户,推荐B产品
+5. **组织穿透**:圈选某客户企业的所有高层决策人
+
+### 8.2 圈人条件
+
+#### 8.2.1 基础条件
+
+圈人条件支持多维度组合查询:
+
+**企业维度条件**:
+- 行业:IN(互联网、金融、制造等)
+- 规模:IN(500人以上、1000人以上等)
+- 地域:IN(北京、上海、深圳等)
+- 客户状态:IN(商机、成交客户等)
+
+**联系人维度条件**:
+- 职级:IN(VP、CXO、总监等)
+- 部门:IN(技术部、产品部等)
+- 决策角色:IN(决策者、影响者等)
+
+**标签条件**:
+- 标签存在性:HAS标签(如"高意向")
+- 标签值:标签值等于/大于/小于某个值
+
+**行为条件**:
+- 互动次数:近30天互动次数 >= 10
+- 最后互动时间:在某个时间范围内
+- 页面浏览:浏览过特定页面
+
+**逻辑关系**:
+- 支持AND、OR组合
+- 支持条件分组
+
+#### 8.2.2 组织关系条件
+
+除了基础条件,还支持基于组织关系的圈人:
+
+**层级条件**:
+- 职级:总监及以上
+- 层级:高层、中层、基层
+
+**部门条件**:
+- 所属部门:IN(技术部、产品部)
+- 包含子部门:是/否
+
+**汇报关系条件**:
+- 某人的所有下属:向下N级
+- 某人的所有上级:向上到顶
+- 某人的同事:共同上级的下属
+
+**组合查询示例**:
+圈选某客户企业(A001)中,技术部或产品部的总监及以上人员,且是张三(CDP_000001)的下属(向下2级)。
+
+### 8.3 圈人引擎
+
+#### 8.3.1 查询优化
+
+对于复杂的圈人条件,采用多阶段查询策略,逐步缩小候选集:
+
+```mermaid
+graph TD
+ A[圈人条件输入] --> B[Stage 1: 基础条件过滤
MySQL/ES
行业、规模、地域等静态属性]
+ B --> C[Stage 2: 标签条件过滤
Redis/HBase
查询标签结果表]
+ C --> D[Stage 3: 行为条件过滤
ClickHouse
查询行为汇总数据]
+ D --> E[Stage 4: 组织关系过滤
Neo4j
查询组织关系图]
+ E --> F[Stage 5: 结果合并去重
返回最终CDP ID列表]
+```
+
+**查询优化策略**:
+
+1. **先过滤后关联**:先用过滤性强的条件缩小候选集
+2. **分阶段查询**:按数据源特点分阶段查询,避免全表扫描
+3. **索引优化**:为常用查询字段建立合适的索引
+4. **缓存结果**:对热点圈人条件缓存查询结果
+5. **异步计算**:复杂圈人任务异步执行,避免超时
+
+#### 8.3.2 圈人服务能力
+
+圈人服务对外提供以下核心能力:
+
+**服务接口清单**:
+
+1. **创建圈人任务**:提交圈人条件,创建圈人任务,返回任务ID
+2. **查询圈人结果**:根据任务ID分页查询圈人结果
+3. **导出圈人结果**:将圈人结果导出为Excel/CSV文件
+4. **推送圈人结果**:将圈人结果推送到外部系统(企微、邮件、广告平台等)
+
+**任务状态管理**:
+- 待执行:任务已创建,等待调度
+- 执行中:任务正在计算
+- 执行成功:任务完成,结果可查询
+- 执行失败:任务失败,记录错误信息
+
+### 8.4 圈人结果应用
+
+圈选结果可以应用到多种场景:
+
+1. **导出**:导出为Excel/CSV,提供给业务团队线下使用
+2. **推送**:
+ - 推送到企业微信:通过企微消息触达客户
+ - 推送到邮件系统:批量发送营销邮件
+ - 推送到短信平台:发送短信通知
+3. **广告投放**:同步到广告平台(如腾讯广告、字节广告),用于Lookalike扩量
+4. **任务分配**:自动创建销售任务,分配给对应销售跟进
+5. **实时触发**:基于用户行为实时触发营销动作(如自动化营销流程)
+
+---
+
+## 九、数据安全与合规
+
+[返回目录](#目录)
+
+### 9.1 合规要求
+
+根据《个人信息保护法》、《数据安全法》等法规,CDP需要满足:
+
+1. **数据最小化**:只采集业务必需的数据,避免过度采集
+2. **明示同意**:用户明确授权后才能采集和使用个人信息
+3. **数据脱敏**:敏感数据加密存储和传输
+4. **访问控制**:基于角色的权限管理,最小权限原则
+5. **审计日志**:记录所有数据访问和操作,可追溯
+6. **数据删除**:用户有权要求删除个人数据,需提供删除机制
+7. **数据导出**:用户有权导出个人数据,需提供导出功能
+8. **安全评估**:定期进行数据安全风险评估
+
+### 9.2 数据脱敏策略
+
+#### 9.2.1 脱敏字段
+
+针对不同类型的敏感信息,采用不同的脱敏策略:
+
+| 字段类型 | 脱敏方式 | 示例 | 适用场景 |
+|---------|---------|------|---------|
+| 手机号 | 中间4位打码 | 138****8000 | 列表展示、报表导出 |
+| 邮箱 | 用户名部分打码 | zha***@example.com | 列表展示、报表导出 |
+| 身份证 | 中间部分打码 | 110***********1234 | 身份验证场景 |
+| 姓名 | 姓氏保留 | 张** | 低敏感场景 |
+| 地址 | 详细地址模糊化 | 北京市朝阳区*** | 区域统计分析 |
+
+#### 9.2.2 加密存储
+
+敏感字段采用AES加密存储:
+
+**加密方案**:
+- 使用AES-256加密算法
+- 密钥管理:采用密钥管理系统(KMS),支持密钥轮转
+- 版本管理:记录加密密钥版本,支持密钥升级
+- 应用层解密:数据在应用层解密后使用,数据库层保持加密状态
+
+**敏感字段表设计要点**:
+- 单独存储敏感字段,与业务表分离
+- 使用VARBINARY类型存储加密后的数据
+- 记录加密密钥版本,便于密钥轮转
+- 严格控制解密权限,最小化明文暴露
+
+### 9.3 权限控制
+
+#### 9.3.1 RBAC模型
+
+采用基于角色的访问控制(RBAC)模型:
+
+**核心概念**:
+- **用户(User)**:系统使用者
+- **角色(Role)**:权限的集合,如"销售主管"、"数据分析师"
+- **权限(Permission)**:具体的操作权限,如"查看客户信息"、"导出数据"
+
+**权限表设计要点**:
+
+**角色表**:
+- 存储角色基本信息:角色ID、角色名称、角色描述
+- 支持角色的启用/禁用
+
+**权限表**:
+- 存储权限定义:权限ID、权限名称
+- 资源类型:ACCOUNT(企业)、CONTACT(联系人)、TAG(标签)
+- 操作类型:READ(查看)、WRITE(编辑)、DELETE(删除)、EXPORT(导出)
+
+**角色权限关联表**:
+- 建立角色与权限的多对多关系
+
+**用户角色关联表**:
+- 建立用户与角色的多对多关系
+- 一个用户可以拥有多个角色
+
+**典型角色定义**:
+- **销售**:查看自己负责的客户、编辑客户信息、圈人导出
+- **销售主管**:查看团队客户、分配客户、审批导出
+- **数据分析师**:查看所有数据、BI分析、无导出权限
+- **系统管理员**:全部权限
+
+#### 9.3.2 数据权限
+
+除了功能权限,还需要控制数据范围权限(行级权限):
+
+**数据权限表设计要点**:
+- 用户ID:权限归属用户
+- 数据类型:ACCOUNT(企业)、CONTACT(联系人)
+- 过滤条件:JSON格式存储数据过滤规则
+
+**典型数据权限规则**:
+
+**示例1:销售只能看到自己负责的客户**
+- 过滤条件:owner_staff_id = 当前用户ID
+
+**示例2:区域经理可以看到整个区域的客户**
+- 过滤条件:region = '华北区'
+
+**示例3:销售VP可以看到所有客户**
+- 过滤条件:无(全量数据)
+
+**数据权限实现方式**:
+- 在应用层查询时自动拼接过滤条件
+- 使用数据库视图限制数据访问范围
+- 使用中间件拦截器统一处理数据权限
+
+### 9.4 审计日志
+
+完善的审计日志是数据安全合规的重要保障:
+
+**操作审计表设计要点**:
+- 记录用户操作:用户ID、用户名
+- 记录操作类型:QUERY(查询)、EXPORT(导出)、UPDATE(更新)、DELETE(删除)
+- 记录资源信息:资源类型、资源ID
+- 记录操作详情:JSON格式存储详细操作内容
+- 记录访问信息:IP地址、User-Agent
+- 记录操作时间:精确到秒
+- 支持按时间分区,便于历史数据归档
+
+**审计日志应用场景**:
+- **合规审计**:满足监管要求,提供操作记录
+- **安全分析**:检测异常操作,如批量导出、越权访问
+- **问题排查**:追溯数据变更历史,定位问题根源
+- **行为分析**:分析用户使用习惯,优化产品体验
+
+**审计日志查询能力**:
+- 按用户查询:查询某个用户的所有操作记录
+- 按时间查询:查询某个时间范围内的操作记录
+- 按操作类型查询:查询所有导出操作、删除操作等
+- 按资源查询:查询某个客户的所有操作历史
+
+---
+
+## 十、技术选型与架构
+
+[返回目录](#目录)
+
+### 10.1 技术栈选型
+
+#### 10.1.1 后端技术栈
+
+| 技术领域 | 选型方案 | 说明 |
+|---------|---------|------|
+| 开发语言 | Java 11+ / Spring Boot | 成熟稳定,生态丰富 |
+| 微服务框架 | Spring Cloud Alibaba | 国内主流,社区活跃 |
+| API网关 | Spring Cloud Gateway | 统一入口,流量控制 |
+| 注册中心 | Nacos | 服务注册与配置管理 |
+| 消息队列 | Kafka | 高吞吐,支持流式处理 |
+| 缓存 | Redis Cluster | 高性能缓存 |
+| 关系数据库 | MySQL 8.0 | 元数据存储 |
+| OLAP数据库 | ClickHouse | 行为事件分析 |
+| 图数据库 | Neo4j | 组织关系查询 |
+| 搜索引擎 | Elasticsearch | 全文搜索 |
+| 实时计算 | Flink | 实时数据处理 |
+| 离线计算 | Spark | 批量数据处理 |
+| 任务调度 | DolphinScheduler | 数据任务编排 |
+| 监控告警 | Prometheus + Grafana | 系统监控 |
+
+#### 10.1.2 前端技术栈
+
+| 技术领域 | 选型方案 |
+|---------|---------|
+| 框架 | React / Vue 3 |
+| UI组件库 | Ant Design / Element Plus |
+| 图表库 | ECharts / AntV |
+| 图可视化 | AntV G6 |
+| 状态管理 | Redux / Pinia |
+| 请求库 | Axios |
+| 构建工具 | Vite / Webpack |
+
+### 10.2 部署架构
+
+#### 10.2.1 云上部署(推荐)
+
+云上部署架构充分利用云平台的弹性伸缩、高可用、托管服务等优势:
+
+```mermaid
+graph TB
+ LB[负载均衡 SLB]
+
+ subgraph K8s集群
+ GW[API网关集群]
+
+ subgraph 应用服务集群
+ APP1[圈人服务]
+ APP2[标签服务]
+ APP3[画像服务]
+ APP4[组织服务]
+ end
+
+ subgraph 数据服务集群
+ DATA1[数据采集服务]
+ DATA2[OneID服务]
+ DATA3[数据质量服务]
+ end
+
+ subgraph 计算服务集群
+ COMP1[Flink集群]
+ COMP2[Spark集群]
+ end
+ end
+
+ subgraph 托管数据库
+ RDS[RDS MySQL]
+ REDIS[Redis Cluster]
+ KAFKA[Kafka集群]
+ end
+
+ subgraph 大数据存储
+ CH[ClickHouse]
+ ES[Elasticsearch]
+ NEO[Neo4j]
+ end
+
+ LB --> GW
+ GW --> APP1
+ GW --> APP2
+ GW --> APP3
+ GW --> APP4
+ GW --> DATA1
+ GW --> DATA2
+ GW --> DATA3
+
+ APP1 --> RDS
+ APP2 --> RDS
+ APP3 --> REDIS
+ APP4 --> NEO
+
+ DATA1 --> KAFKA
+ DATA2 --> RDS
+
+ KAFKA --> COMP1
+ COMP1 --> CH
+ COMP2 --> CH
+```
+
+**云上部署优势**:
+- **弹性伸缩**:根据负载自动调整资源,按需付费
+- **高可用**:跨可用区容灾,自动故障切换
+- **托管服务**:RDS、Kafka等托管服务,减少运维成本
+- **安全隔离**:VPC网络隔离,安全组访问控制
+- **监控告警**:云平台提供完善的监控和告警能力
+
+**推荐云平台**:
+- 阿里云:完整的大数据产品线,适合国内客户
+- 腾讯云:企微生态整合,适合重度使用企微的场景
+- AWS:全球部署,适合海外业务
+
+#### 10.2.2 私有化部署
+
+适用于对数据安全要求极高、需要数据主权的客户:
+
+```mermaid
+graph TB
+ F5[硬件负载均衡 F5/Nginx]
+
+ subgraph 应用服务器集群
+ AS1[应用服务器1]
+ AS2[应用服务器2]
+ AS3[应用服务器3]
+ end
+
+ subgraph 数据库服务器
+ DB1[MySQL主库]
+ DB2[MySQL从库]
+ end
+
+ subgraph 缓存服务器集群
+ CACHE1[Redis节点1]
+ CACHE2[Redis节点2]
+ CACHE3[Redis节点3]
+ end
+
+ subgraph 消息队列集群
+ MQ1[Kafka节点1]
+ MQ2[Kafka节点2]
+ MQ3[Kafka节点3]
+ end
+
+ subgraph 大数据集群
+ BIG[ClickHouse/Flink/Spark集群
多节点部署]
+ end
+
+ F5 --> AS1
+ F5 --> AS2
+ F5 --> AS3
+
+ AS1 --> DB1
+ AS2 --> DB1
+ AS3 --> DB1
+
+ DB1 --> DB2
+
+ AS1 --> CACHE1
+ AS1 --> MQ1
+
+ MQ1 --> BIG
+```
+
+**私有化部署特点**:
+- **数据主权**:数据完全掌控在客户手中
+- **网络隔离**:部署在客户内网,与外网物理隔离
+- **定制化强**:可根据客户需求深度定制
+- **运维成本高**:需要客户自行运维,或提供驻场服务
+
+**硬件配置建议**:
+- **应用服务器**:16核32G内存,至少3台
+- **数据库服务器**:32核64G内存,SSD存储,主从架构
+- **缓存服务器**:16核32G内存,至少3台组成集群
+- **消息队列**:16核32G内存,至少3台组成集群
+- **大数据集群**:根据数据量规划,至少5台起步
+
+### 10.3 核心服务设计
+
+#### 10.3.1 服务拆分
+
+基于微服务架构,按照业务领域拆分服务:
+
+**服务清单**:
+
+| 服务名称 | 职责说明 |
+|---------|---------|
+| cdp-gateway-service | API网关,统一入口,路由转发、鉴权、限流 |
+| cdp-user-service | 用户权限服务,用户管理、角色管理、权限控制 |
+| cdp-collection-service | 数据采集服务,多源数据接入、数据清洗 |
+| cdp-oneid-service | OneID服务,身份识别、ID-Mapping、客户视图 |
+| cdp-organization-service | 组织架构服务,组织关系管理、关系查询 |
+| cdp-tag-service | 标签服务,标签配置、标签计算、标签查询 |
+| cdp-audience-service | 圈人服务,圈人条件解析、圈人执行、结果导出 |
+| cdp-profile-service | 画像服务,客户360画像、画像查询 |
+| cdp-data-quality-service | 数据质量服务,数据质量监控、数据清洗规则 |
+| cdp-export-service | 数据导出服务,数据导出、推送到外部系统 |
+
+**服务拆分原则**:
+- **高内聚低耦合**:同一业务领域的功能在一个服务内
+- **独立部署**:每个服务可以独立部署、独立扩展
+- **数据隔离**:每个服务有独立的数据库/Schema
+- **接口稳定**:服务间通过稳定的API通信
+
+#### 10.3.2 服务通信
+
+服务间通信采用同步+异步结合的方式:
+
+**同步调用**:
+- **协议**:HTTP/REST
+- **框架**:OpenFeign
+- **适用场景**:实时查询、事务性操作
+- **超时控制**:设置合理的超时时间(如3秒)
+- **重试策略**:幂等接口支持重试
+
+**异步调用**:
+- **消息队列**:Kafka
+- **适用场景**:数据同步、事件通知、批量处理
+- **消息格式**:JSON,包含消息ID、时间戳、业务数据
+- **消费模式**:支持广播和点对点
+
+**服务降级**:
+- **限流**:集成Sentinel,防止服务过载
+- **熔断**:快速失败,避免雪崩
+- **降级**:返回默认值或缓存数据
+
+**链路追踪**:
+- **APM工具**:SkyWalking
+- **功能**:请求链路追踪、性能分析、异常排查
+- **Trace ID**:全链路跟踪请求
+
+---
+
+## 十一、系统实施路线图
+
+[返回目录](#目录)
+
+### 11.1 Phase 1: MVP版本 (2-3个月)
+
+**核心目标**:快速上线基础功能,验证业务价值
+
+**功能范围**:
+- **数据采集**:CRM同步、企业微信接入
+- **OneID**:基本的ID-Mapping能力
+- **客户管理**:客户企业、联系人基础信息管理
+- **组织架构**:基础的上下级关系查询
+- **标签体系**:10-20个核心业务标签
+- **圈人能力**:基于标签的简单圈人
+- **销售工作台**:客户列表、客户详情、组织架构图
+
+**技术实现**:
+- 关系型数据库为主(MySQL)
+- 简单的组织关系查询(SQL递归查询)
+- 前端单体应用
+
+**交付成果**:
+- 可用的销售工作台
+- 基础的客户360画像
+- 简单的圈人导出功能
+
+### 11.2 Phase 2: 增强版本 (3-4个月)
+
+**核心目标**:完善核心能力,支持更复杂的业务场景
+
+**功能范围**:
+- **数据采集**:第三方数据接入、Web埋点SDK
+- **OneID**:多源数据深度打通、ID合并策略
+- **组织架构**:矩阵式组织、复杂关系查询(图数据库)
+- **标签体系**:50+标签、自定义标签平台、标签自动更新
+- **圈人能力**:组织关系圈人、复杂条件圈人、圈人结果推送
+- **数据分析**:客户分析报表、销售漏斗、客户健康度
+
+**技术升级**:
+- 引入Neo4j图数据库,优化组织关系查询
+- 引入ClickHouse,支持海量行为数据分析
+- 引入Flink,支持实时数据处理
+- 微服务化改造
+
+**交付成果**:
+- 完整的标签平台
+- 强大的圈人能力
+- 组织穿透场景落地
+
+### 11.3 Phase 3: 智能版本 (4-6个月)
+
+**核心目标**:引入AI能力,提升智能化水平
+
+**功能范围**:
+- **预测类标签**:成交概率、流失风险、客户价值评分
+- **智能推荐**:下一步行动建议、推荐联系人、推荐话术
+- **自然语言查询**:通过自然语言描述圈人条件
+- **异常检测**:数据质量监控、异常行为识别
+- **自动化营销**:基于触发条件的自动化流程
+
+**技术升级**:
+- 引入机器学习平台(如MLflow)
+- 引入NLP模型(如BERT)
+- 引入知识图谱
+
+**交付成果**:
+- 智能化的销售辅助能力
+- 自动化营销能力
+- 从"被动查询"到"主动洞察"
+
+---
+
+## 十二、成功案例参考
+
+[返回目录](#目录)
+
+### 12.1 客户画像场景
+
+**业务场景**:销售拜访某客户前,快速了解客户全貌
+
+**解决方案**:
+1. 销售在企微侧边栏打开CDP客户画像
+2. 展示客户企业基本信息(行业、规模、经营状况)
+3. 展示组织架构图,标注已触达联系人
+4. 展示关键决策人(CEO、CTO等),提示是否已触达
+5. 展示近期互动记录(聊天、邮件、会议)
+6. 展示客户意向度、成交概率等智能标签
+7. 推荐下一步行动(如"建议约见技术VP李总")
+
+**业务价值**:
+- 销售拜访准备时间从2小时缩短到30分钟
+- 触达关键决策人的概率提升40%
+- 商机转化率提升25%
+
+### 12.2 组织穿透场景
+
+**业务场景**:已经触达某客户的技术经理,希望触达其上级技术VP
+
+**解决方案**:
+1. 在CDP中查询该技术经理的组织关系
+2. 系统自动展示其直属上级"技术VP-李总"
+3. 展示李总的画像:职位、联系方式、近期活跃情况
+4. 展示李总的关注点:曾查看过产品方案、参加过线上会议
+5. 推荐触达策略:通过现有联系人引荐、或发送定向内容
+
+**业务价值**:
+- 决策链触达完整度从30%提升到70%
+- 大单成交周期缩短20%
+
+### 12.3 精准营销场景
+
+**业务场景**:新产品发布,需要圈选目标客户进行推广
+
+**圈人条件**:
+- 行业:互联网、金融
+- 规模:500人以上
+- 客户阶段:商机阶段
+- 联系人层级:VP/CXO
+- 意向度:高意向
+- 互动情况:近30天有互动
+- 组织关系:已触达技术部门
+
+**执行动作**:
+- 圈选出500个目标联系人
+- 通过企业微信推送产品介绍
+- 邀请参加线上产品发布会
+- 销售跟进重点客户
+
+**业务价值**:
+- 营销触达精准度提升60%
+- 产品发布会参会率提升3倍
+- 新产品试用转化率提升50%
+
+---
+
+## 十三、总结与展望
+
+[返回目录](#目录)
+
+### 13.1 企业级CDP与C端CDP的核心差异
+
+| 维度 | C端CDP | 企业级CDP |
+|-----|--------|-----------|
+| 客户主体 | 个人消费者 | 企业+联系人 |
+| 数据规模 | 千万-亿级用户 | 万-百万级企业 |
+| 核心关系 | 用户画像 | 组织架构关系 |
+| 决策模式 | 个人决策 | 多人协同决策 |
+| 生命周期 | 较短(数月) | 较长(数年) |
+| 典型场景 | 精准投放、个性化推荐 | 销售赋能、组织穿透 |
+
+### 13.2 关键成功要素
+
+1. **数据质量**:GIGO(Garbage In, Garbage Out),数据质量是CDP的生命线
+2. **组织关系**:这是企业级CDP的核心竞争力,必须重点投入
+3. **OneID精准度**:直接影响客户画像的准确性
+4. **业务深度结合**:CDP不是数据仓库,必须与业务场景深度结合
+5. **数据安全合规**:红线问题,必须严格遵守
+
+### 13.3 未来演进方向
+
+1. **实时化**:从T+1向实时CDP演进,支持秒级的数据更新
+2. **智能化**:引入更多AI能力,从被动查询到主动洞察
+3. **开放化**:通过API、SDK开放CDP能力,构建数据生态
+4. **私有化**:支持私有化部署,满足大型企业的数据主权诉求
+5. **行业化**:针对不同行业(金融、教育、制造)提供行业解决方案
+
+---
+
+## 附录
+
+[返回目录](#目录)
+
+### 附录A:关键指标定义
+
+| 指标名称 | 定义 | 计算公式 |
+|---------|------|---------|
+| 客户覆盖率 | 已录入CDP的客户占总客户的比例 | CDP客户数 / 总客户数 |
+| OneID准确率 | OneID匹配正确的比例 | 正确匹配数 / 总匹配数 |
+| 标签覆盖率 | 有标签的客户占总客户的比例 | 有标签客户数 / 总客户数 |
+| 标签平均数 | 每个客户平均拥有的标签数 | 总标签数 / 客户数 |
+| 组织完整度 | 组织架构信息完整的客户比例 | 有组织信息客户数 / 总客户数 |
+| 数据新鲜度 | 数据最近更新的时间 | 当前时间 - 最后更新时间 |
+
+### 附录B:核心服务接口
+
+**OneID服务接口**:
+- GET `/api/v1/oneid/customer/{cdpId}` - 获取客户画像
+- POST `/api/v1/oneid/bind` - 绑定ID
+- POST `/api/v1/oneid/merge` - 合并ID
+
+**组织架构服务接口**:
+- GET `/api/v1/org/manager/{cdpId}` - 查询上级
+- GET `/api/v1/org/reports/{cdpId}` - 查询下属
+- GET `/api/v1/org/tree/{accountId}` - 查询组织树
+
+**标签服务接口**:
+- GET `/api/v1/tag/list` - 标签列表
+- POST `/api/v1/tag/calculate` - 计算标签
+- GET `/api/v1/tag/customer/{cdpId}` - 查询客户标签
+
+**圈人服务接口**:
+- POST `/api/v1/audience/create` - 创建圈人任务
+- GET `/api/v1/audience/{audienceId}/result` - 查询圈人结果
+- POST `/api/v1/audience/{audienceId}/export` - 导出圈人结果
+
+---
+
+**文档版本**:v2.0
+**最后更新**:2024-10-28
+**作者**:CDP项目组
+
+---
+
+## 问题讨论与反馈
+
+如您对本设计方案有任何疑问或建议,请联系项目组进行讨论。
+
+**关键待确认事项**:
+1. 数据源系统的详细对接规范(CRM系统接口文档、企微API权限)
+2. 组织架构的复杂度(是否存在矩阵式管理、虚线汇报等特殊情况)
+3. 性能要求(并发用户数、查询响应时间SLA)
+4. 预算与人力资源(开发团队规模、预算范围)
+5. 上线时间要求(是否有硬性deadline)
+
+[返回目录](#目录)
diff --git a/docs/graph-definition-examples.md b/docs/graph-definition-examples.md
new file mode 100644
index 000000000..3f1c2f534
--- /dev/null
+++ b/docs/graph-definition-examples.md
@@ -0,0 +1,899 @@
+# StreamGraph定义结构说明
+
+## 1. graph_definition结构概述
+
+`graph_definition`是JSON格式,存储StreamGraph的完整定义,包括节点(nodes)和边(edges)。
+
+### 1.1 基本结构
+
+```json
+{
+ "version": "1.0",
+ "nodes": [
+ {
+ "node_id": "唯一节点ID",
+ "node_name": "节点名称",
+ "node_type": "SOURCE/OPERATOR/SINK",
+ "operator_type": "具体算子类型",
+ "config": {
+ "算子特定配置": "..."
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "边ID",
+ "source_node_id": "源节点ID",
+ "target_node_id": "目标节点ID"
+ }
+ ],
+ "global_config": {
+ "全局配置": "..."
+ }
+}
+```
+
+## 2. 节点类型详解
+
+### 2.1 SOURCE节点
+
+Source节点定义数据源。
+
+```json
+{
+ "node_id": "source-kafka-001",
+ "node_name": "用户事件源",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "config": {
+ "datasource_id": "kafka-prod-cluster",
+ "topics": ["user-events", "user-actions"],
+ "group_id": "etl-consumer-group-1",
+ "auto_offset_reset": "latest",
+ "poll_timeout_ms": 1000,
+ "max_poll_records": 500,
+ "enable_auto_commit": false,
+ "properties": {
+ "max.partition.fetch.bytes": "1048576"
+ }
+ }
+}
+```
+
+**常见Source类型**:
+
+#### JDBC_SOURCE
+```json
+{
+ "node_id": "source-mysql-001",
+ "node_name": "订单数据源",
+ "node_type": "SOURCE",
+ "operator_type": "JDBC_SOURCE",
+ "config": {
+ "datasource_id": "mysql-prod",
+ "query": "SELECT * FROM orders WHERE updated_at > ? AND updated_at <= ?",
+ "fetch_size": 1000,
+ "poll_interval_seconds": 60,
+ "timestamp_column": "updated_at",
+ "start_timestamp": "2025-01-01 00:00:00"
+ }
+}
+```
+
+#### HTTP_SOURCE
+```json
+{
+ "node_id": "source-api-001",
+ "node_name": "API数据源",
+ "node_type": "SOURCE",
+ "operator_type": "HTTP_SOURCE",
+ "config": {
+ "url": "https://api.example.com/data",
+ "method": "GET",
+ "headers": {
+ "Authorization": "Bearer ${token}",
+ "Content-Type": "application/json"
+ },
+ "poll_interval_seconds": 30,
+ "timeout_seconds": 10,
+ "retry_times": 3
+ }
+}
+```
+
+#### FILE_SOURCE
+```json
+{
+ "node_id": "source-file-001",
+ "node_name": "CSV文件源",
+ "node_type": "SOURCE",
+ "operator_type": "FILE_SOURCE",
+ "config": {
+ "path": "/data/input/*.csv",
+ "format": "CSV",
+ "charset": "UTF-8",
+ "delimiter": ",",
+ "has_header": true,
+ "watch_mode": "CONTINUOUS",
+ "scan_interval_seconds": 10
+ }
+}
+```
+
+### 2.2 OPERATOR节点
+
+Operator节点定义数据转换操作。
+
+#### MAP算子
+```json
+{
+ "node_id": "operator-map-001",
+ "node_name": "解析JSON",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "config": {
+ "function_class": "com.example.etl.function.ParseJsonFunction",
+ "function_config": {
+ "output_fields": ["user_id", "event_type", "timestamp", "properties"]
+ }
+ }
+}
+```
+
+#### FILTER算子
+```json
+{
+ "node_id": "operator-filter-001",
+ "node_name": "过滤活跃用户",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "config": {
+ "predicate_class": "com.example.etl.predicate.ActiveUserPredicate",
+ "predicate_expression": "user.is_active == true AND user.register_days > 7"
+ }
+}
+```
+
+#### FLATMAP算子
+```json
+{
+ "node_id": "operator-flatmap-001",
+ "node_name": "拆分数组",
+ "node_type": "OPERATOR",
+ "operator_type": "FLATMAP",
+ "config": {
+ "function_class": "com.example.etl.function.SplitArrayFunction",
+ "source_field": "tags",
+ "output_field": "tag"
+ }
+}
+```
+
+#### AGGREGATE算子(有状态)
+```json
+{
+ "node_id": "operator-aggregate-001",
+ "node_name": "按城市聚合",
+ "node_type": "OPERATOR",
+ "operator_type": "AGGREGATE",
+ "config": {
+ "group_by_fields": ["city"],
+ "aggregations": [
+ {
+ "field": "user_id",
+ "function": "COUNT",
+ "alias": "user_count"
+ },
+ {
+ "field": "amount",
+ "function": "SUM",
+ "alias": "total_amount"
+ },
+ {
+ "field": "amount",
+ "function": "AVG",
+ "alias": "avg_amount"
+ }
+ ],
+ "window": {
+ "type": "TUMBLING",
+ "size": "5m"
+ }
+ }
+}
+```
+
+#### WINDOW算子(有状态)
+```json
+{
+ "node_id": "operator-window-001",
+ "node_name": "5分钟滚动窗口",
+ "node_type": "OPERATOR",
+ "operator_type": "WINDOW",
+ "config": {
+ "window_type": "TUMBLING",
+ "window_size": "5m",
+ "allowed_lateness": "1m",
+ "trigger": "ON_TIME"
+ }
+}
+```
+
+#### JOIN算子(有状态)
+```json
+{
+ "node_id": "operator-join-001",
+ "node_name": "关联用户信息",
+ "node_type": "OPERATOR",
+ "operator_type": "JOIN",
+ "config": {
+ "join_type": "LEFT",
+ "left_key": "user_id",
+ "right_key": "id",
+ "right_source": {
+ "type": "CACHE",
+ "cache_name": "user_info_cache"
+ },
+ "output_fields": ["*", "user.name", "user.age", "user.city"]
+ }
+}
+```
+
+#### DEDUPLICATE算子(有状态)
+```json
+{
+ "node_id": "operator-dedup-001",
+ "node_name": "去重",
+ "node_type": "OPERATOR",
+ "operator_type": "DEDUPLICATE",
+ "config": {
+ "key_fields": ["user_id", "event_id"],
+ "time_window": "1h",
+ "keep_first": true
+ }
+}
+```
+
+### 2.3 SINK节点
+
+Sink节点定义数据输出。
+
+#### JDBC_SINK
+```json
+{
+ "node_id": "sink-mysql-001",
+ "node_name": "写入MySQL",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "config": {
+ "datasource_id": "mysql-warehouse",
+ "table": "user_statistics",
+ "write_mode": "UPSERT",
+ "unique_key": ["date", "city"],
+ "batch_size": 100,
+ "flush_interval_ms": 5000,
+ "max_retries": 3,
+ "field_mapping": {
+ "stat_date": "date",
+ "city_name": "city",
+ "user_cnt": "user_count",
+ "total_amt": "total_amount"
+ }
+ }
+}
+```
+
+#### KAFKA_SINK
+```json
+{
+ "node_id": "sink-kafka-001",
+ "node_name": "写入Kafka",
+ "node_type": "SINK",
+ "operator_type": "KAFKA_SINK",
+ "config": {
+ "datasource_id": "kafka-prod-cluster",
+ "topic": "processed-events",
+ "key_field": "user_id",
+ "partition_strategy": "HASH",
+ "serialization": "JSON",
+ "compression": "gzip",
+ "acks": "all",
+ "batch_size": 100,
+ "linger_ms": 10
+ }
+}
+```
+
+#### ELASTICSEARCH_SINK
+```json
+{
+ "node_id": "sink-es-001",
+ "node_name": "写入ES",
+ "node_type": "SINK",
+ "operator_type": "ELASTICSEARCH_SINK",
+ "config": {
+ "datasource_id": "elasticsearch-cluster",
+ "index": "user_events_{date}",
+ "id_field": "event_id",
+ "batch_size": 500,
+ "flush_interval_ms": 3000,
+ "max_retries": 3
+ }
+}
+```
+
+#### FILE_SINK
+```json
+{
+ "node_id": "sink-file-001",
+ "node_name": "写入文件",
+ "node_type": "SINK",
+ "operator_type": "FILE_SINK",
+ "config": {
+ "path": "/data/output/result_{date}.json",
+ "format": "JSON",
+ "charset": "UTF-8",
+ "rolling_policy": {
+ "type": "TIME",
+ "interval": "1h"
+ },
+ "compression": "gzip"
+ }
+}
+```
+
+## 3. 边(Edge)定义
+
+边描述节点之间的数据流向关系。
+
+```json
+{
+ "edge_id": "edge-001",
+ "source_node_id": "source-kafka-001",
+ "target_node_id": "operator-map-001",
+ "edge_type": "FORWARD"
+}
+```
+
+**边类型**:
+- `FORWARD`: 一对一转发(默认)
+- `BROADCAST`: 广播到所有下游
+- `SHUFFLE`: 按key重新分区(暂时不用,单机执行)
+
+## 4. 完整示例
+
+### 4.1 简单ETL任务
+
+**场景**: 从Kafka读取数据 → 解析JSON → 过滤 → 写入MySQL
+
+```json
+{
+ "version": "1.0",
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "Kafka数据源",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "config": {
+ "datasource_id": "kafka-prod",
+ "topics": ["user-events"],
+ "group_id": "etl-simple",
+ "auto_offset_reset": "latest"
+ }
+ },
+ {
+ "node_id": "op-parse-001",
+ "node_name": "解析JSON",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "config": {
+ "function_class": "com.example.ParseJsonFunction"
+ }
+ },
+ {
+ "node_id": "op-filter-001",
+ "node_name": "过滤有效数据",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "config": {
+ "predicate_expression": "data.user_id != null AND data.event_type != null"
+ }
+ },
+ {
+ "node_id": "sink-001",
+ "node_name": "写入MySQL",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "config": {
+ "datasource_id": "mysql-warehouse",
+ "table": "user_events",
+ "batch_size": 100
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-parse-001"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-filter-001"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-filter-001",
+ "target_node_id": "sink-001"
+ }
+ ],
+ "global_config": {
+ "buffer_size": 1000,
+ "backpressure_strategy": "BUFFER"
+ }
+}
+```
+
+### 4.2 带聚合的实时统计任务
+
+**场景**: Kafka → 解析 → 窗口聚合 → 写入MySQL和Redis
+
+```json
+{
+ "version": "1.0",
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "订单事件源",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "config": {
+ "datasource_id": "kafka-prod",
+ "topics": ["order-events"],
+ "group_id": "order-stats-etl"
+ }
+ },
+ {
+ "node_id": "op-parse-001",
+ "node_name": "解析订单JSON",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "config": {
+ "function_class": "com.example.ParseOrderFunction"
+ }
+ },
+ {
+ "node_id": "op-window-001",
+ "node_name": "5分钟窗口",
+ "node_type": "OPERATOR",
+ "operator_type": "WINDOW",
+ "config": {
+ "window_type": "TUMBLING",
+ "window_size": "5m"
+ }
+ },
+ {
+ "node_id": "op-agg-001",
+ "node_name": "按城市聚合",
+ "node_type": "OPERATOR",
+ "operator_type": "AGGREGATE",
+ "config": {
+ "group_by_fields": ["city"],
+ "aggregations": [
+ {
+ "field": "order_id",
+ "function": "COUNT",
+ "alias": "order_count"
+ },
+ {
+ "field": "amount",
+ "function": "SUM",
+ "alias": "total_amount"
+ }
+ ]
+ }
+ },
+ {
+ "node_id": "sink-mysql-001",
+ "node_name": "写入MySQL",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "config": {
+ "datasource_id": "mysql-warehouse",
+ "table": "order_stats_5m",
+ "write_mode": "INSERT",
+ "batch_size": 50
+ }
+ },
+ {
+ "node_id": "sink-redis-001",
+ "node_name": "写入Redis",
+ "node_type": "SINK",
+ "operator_type": "REDIS_SINK",
+ "config": {
+ "datasource_id": "redis-cache",
+ "key_pattern": "order:stats:5m:{city}",
+ "expire_seconds": 3600
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-parse-001"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-window-001"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-window-001",
+ "target_node_id": "op-agg-001"
+ },
+ {
+ "edge_id": "edge-004",
+ "source_node_id": "op-agg-001",
+ "target_node_id": "sink-mysql-001"
+ },
+ {
+ "edge_id": "edge-005",
+ "source_node_id": "op-agg-001",
+ "target_node_id": "sink-redis-001"
+ }
+ ],
+ "global_config": {
+ "checkpoint_enabled": true,
+ "checkpoint_interval_seconds": 60
+ }
+}
+```
+
+### 4.3 复杂的多分支处理任务
+
+**场景**: 一个Source → 多个处理分支 → 多个Sink
+
+```json
+{
+ "version": "1.0",
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "用户行为日志",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "config": {
+ "datasource_id": "kafka-prod",
+ "topics": ["user-behavior"],
+ "group_id": "behavior-etl"
+ }
+ },
+ {
+ "node_id": "op-parse-001",
+ "node_name": "解析日志",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "config": {
+ "function_class": "com.example.ParseBehaviorFunction"
+ }
+ },
+ {
+ "node_id": "op-filter-login-001",
+ "node_name": "过滤登录事件",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "config": {
+ "predicate_expression": "event_type == 'LOGIN'"
+ }
+ },
+ {
+ "node_id": "op-filter-purchase-001",
+ "node_name": "过滤购买事件",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "config": {
+ "predicate_expression": "event_type == 'PURCHASE'"
+ }
+ },
+ {
+ "node_id": "op-filter-view-001",
+ "node_name": "过滤浏览事件",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "config": {
+ "predicate_expression": "event_type == 'VIEW'"
+ }
+ },
+ {
+ "node_id": "op-enrich-001",
+ "node_name": "关联用户信息",
+ "node_type": "OPERATOR",
+ "operator_type": "JOIN",
+ "config": {
+ "join_type": "LEFT",
+ "left_key": "user_id",
+ "right_key": "id",
+ "right_source": {
+ "type": "JDBC",
+ "datasource_id": "mysql-user",
+ "query": "SELECT id, name, city, vip_level FROM users WHERE id IN (?)"
+ }
+ }
+ },
+ {
+ "node_id": "sink-login-001",
+ "node_name": "登录日志入库",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "config": {
+ "datasource_id": "mysql-log",
+ "table": "login_logs",
+ "batch_size": 100
+ }
+ },
+ {
+ "node_id": "sink-purchase-001",
+ "node_name": "购买记录入库",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "config": {
+ "datasource_id": "mysql-order",
+ "table": "purchase_records",
+ "batch_size": 50
+ }
+ },
+ {
+ "node_id": "sink-view-001",
+ "node_name": "浏览行为入ES",
+ "node_type": "SINK",
+ "operator_type": "ELASTICSEARCH_SINK",
+ "config": {
+ "datasource_id": "es-behavior",
+ "index": "view_logs_{date}",
+ "batch_size": 500
+ }
+ },
+ {
+ "node_id": "sink-all-001",
+ "node_name": "全量数据归档",
+ "node_type": "SINK",
+ "operator_type": "FILE_SINK",
+ "config": {
+ "path": "/data/archive/behavior_{date}.json",
+ "format": "JSON",
+ "rolling_policy": {
+ "type": "SIZE",
+ "max_size_mb": 100
+ }
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-parse-001"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-filter-login-001"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-filter-purchase-001"
+ },
+ {
+ "edge_id": "edge-004",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-filter-view-001"
+ },
+ {
+ "edge_id": "edge-005",
+ "source_node_id": "op-filter-login-001",
+ "target_node_id": "sink-login-001"
+ },
+ {
+ "edge_id": "edge-006",
+ "source_node_id": "op-filter-purchase-001",
+ "target_node_id": "op-enrich-001"
+ },
+ {
+ "edge_id": "edge-007",
+ "source_node_id": "op-enrich-001",
+ "target_node_id": "sink-purchase-001"
+ },
+ {
+ "edge_id": "edge-008",
+ "source_node_id": "op-filter-view-001",
+ "target_node_id": "sink-view-001"
+ },
+ {
+ "edge_id": "edge-009",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "sink-all-001"
+ }
+ ],
+ "global_config": {
+ "buffer_size": 2000,
+ "backpressure_strategy": "DROP_OLDEST",
+ "checkpoint_enabled": true,
+ "checkpoint_interval_seconds": 300
+ }
+}
+```
+
+### 4.4 批处理任务示例
+
+**场景**: 从MySQL增量读取 → 转换 → 写入数据仓库
+
+```json
+{
+ "version": "1.0",
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "MySQL增量源",
+ "node_type": "SOURCE",
+ "operator_type": "JDBC_SOURCE",
+ "config": {
+ "datasource_id": "mysql-app",
+ "query": "SELECT * FROM orders WHERE updated_at > ? AND updated_at <= ? ORDER BY updated_at",
+ "fetch_size": 5000,
+ "timestamp_column": "updated_at",
+ "increment_type": "TIME_BASED"
+ }
+ },
+ {
+ "node_id": "op-transform-001",
+ "node_name": "数据转换",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "config": {
+ "function_class": "com.example.OrderTransformFunction",
+ "function_config": {
+ "date_format": "yyyy-MM-dd HH:mm:ss",
+ "timezone": "Asia/Shanghai"
+ }
+ }
+ },
+ {
+ "node_id": "op-dedup-001",
+ "node_name": "去重",
+ "node_type": "OPERATOR",
+ "operator_type": "DEDUPLICATE",
+ "config": {
+ "key_fields": ["order_id"],
+ "keep_first": false
+ }
+ },
+ {
+ "node_id": "sink-001",
+ "node_name": "写入数仓",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "config": {
+ "datasource_id": "mysql-dw",
+ "table": "dw_orders",
+ "write_mode": "UPSERT",
+ "unique_key": ["order_id"],
+ "batch_size": 1000,
+ "use_transaction": true
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-transform-001"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-transform-001",
+ "target_node_id": "op-dedup-001"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-dedup-001",
+ "target_node_id": "sink-001"
+ }
+ ],
+ "global_config": {
+ "job_type": "BATCH",
+ "checkpoint_enabled": false
+ }
+}
+```
+
+## 5. 全局配置说明
+
+```json
+{
+ "global_config": {
+ "buffer_size": 1000,
+ "backpressure_strategy": "BUFFER",
+ "checkpoint_enabled": true,
+ "checkpoint_interval_seconds": 60,
+ "restart_on_failure": true,
+ "max_restart_attempts": 3,
+ "error_handling": {
+ "on_source_error": "RETRY",
+ "on_operator_error": "SKIP",
+ "on_sink_error": "FAIL"
+ }
+ }
+}
+```
+
+**配置项说明**:
+- `buffer_size`: 数据缓冲区大小
+- `backpressure_strategy`: 背压策略(BUFFER/DROP/ERROR)
+- `checkpoint_enabled`: 是否启用检查点
+- `checkpoint_interval_seconds`: 检查点间隔
+- `error_handling`: 错误处理策略
+
+## 6. 图定义的可视化表示
+
+### 简单线性流程
+```
+┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
+│ Source │───▶│ Map │───▶│ Filter │───▶│ Sink │
+└──────────┘ └──────────┘ └──────────┘ └──────────┘
+```
+
+### 多分支流程
+```
+ ┌──────────┐ ┌──────────┐
+ ┌──▶│ Filter 1 │───▶│ Sink 1 │
+ │ └──────────┘ └──────────┘
+┌──────────┐│ ┌──────────┐ ┌──────────┐
+│ Source ├┼──▶│ Filter 2 │───▶│ Sink 2 │
+└──────────┘│ └──────────┘ └──────────┘
+ │ ┌──────────┐ ┌──────────┐
+ └──▶│ Filter 3 │───▶│ Sink 3 │
+ └──────────┘ └──────────┘
+```
+
+### 聚合流程
+```
+┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
+│ Source │───▶│ Window │───▶│ Aggregate│───▶│ Sink │
+└──────────┘ └──────────┘ └──────────┘ └──────────┘
+ │
+ └──────────────┐
+ ▼
+ [State Store]
+```
+
+## 7. 建议和最佳实践
+
+### 7.1 节点命名规范
+- 使用有意义的名称
+- 按类型添加前缀:source-、op-、sink-
+- 使用连字符分隔单词
+
+### 7.2 配置管理
+- 敏感信息使用占位符:`${variable_name}`
+- 在运行时从配置中心或环境变量读取
+- 避免硬编码
+
+### 7.3 错误处理
+- Source错误:重试
+- Operator错误:跳过或记录到死信队列
+- Sink错误:重试或失败
+
+### 7.4 性能优化
+- 合理设置batch_size
+- 调整buffer_size避免内存溢出
+- 使用合适的window大小
+
+---
+
+**文档版本**: v1.0
+**最后更新**: 2025-11-09
diff --git a/docs/graph-definition-improved.md b/docs/graph-definition-improved.md
new file mode 100644
index 000000000..5ca70590a
--- /dev/null
+++ b/docs/graph-definition-improved.md
@@ -0,0 +1,543 @@
+# StreamGraph定义改进方案
+
+## 问题:上下游关系不清晰
+
+当前的graph_definition设计中,节点和边是分离的,不够直观:
+
+```json
+{
+ "nodes": [
+ {"node_id": "node-1", ...},
+ {"node_id": "node-2", ...},
+ {"node_id": "node-3", ...}
+ ],
+ "edges": [
+ {"source_node_id": "node-1", "target_node_id": "node-2"},
+ {"source_node_id": "node-2", "target_node_id": "node-3"}
+ ]
+}
+```
+
+**问题**:
+- ❌ 需要在edges中查找才能知道上下游关系
+- ❌ 节点多了之后很难追踪数据流向
+- ❌ 修改连接关系容易出错
+
+## 解决方案1:在节点中添加上下游信息(推荐)
+
+### 方案A:添加辅助字段
+
+在每个节点中添加`upstream_nodes`和`downstream_nodes`字段:
+
+```json
+{
+ "version": "1.0",
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "Kafka数据源",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "upstream_nodes": [],
+ "downstream_nodes": ["op-parse-001"],
+ "config": {...}
+ },
+ {
+ "node_id": "op-parse-001",
+ "node_name": "解析JSON",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "upstream_nodes": ["source-001"],
+ "downstream_nodes": ["op-filter-001"],
+ "config": {...}
+ },
+ {
+ "node_id": "op-filter-001",
+ "node_name": "过滤",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "upstream_nodes": ["op-parse-001"],
+ "downstream_nodes": ["sink-001"],
+ "config": {...}
+ },
+ {
+ "node_id": "sink-001",
+ "node_name": "写入MySQL",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "upstream_nodes": ["op-filter-001"],
+ "downstream_nodes": [],
+ "config": {...}
+ }
+ ],
+ "edges": [
+ {"edge_id": "edge-001", "source_node_id": "source-001", "target_node_id": "op-parse-001"},
+ {"edge_id": "edge-002", "source_node_id": "op-parse-001", "target_node_id": "op-filter-001"},
+ {"edge_id": "edge-003", "source_node_id": "op-filter-001", "target_node_id": "sink-001"}
+ ]
+}
+```
+
+**优点**:
+- ✅ 一眼就能看出节点的上下游
+- ✅ 保留edges定义,用于详细配置
+- ✅ upstream_nodes和downstream_nodes可以从edges自动生成
+
+**缺点**:
+- ⚠️ 信息有冗余(需要保持一致性)
+
+### 方案B:嵌套结构(链式定义)
+
+直接在节点中定义下游节点:
+
+```json
+{
+ "version": "1.0",
+ "pipeline": {
+ "source": {
+ "node_id": "source-001",
+ "node_name": "Kafka数据源",
+ "operator_type": "KAFKA_SOURCE",
+ "config": {...},
+ "next": {
+ "node_id": "op-parse-001",
+ "node_name": "解析JSON",
+ "operator_type": "MAP",
+ "config": {...},
+ "next": {
+ "node_id": "op-filter-001",
+ "node_name": "过滤",
+ "operator_type": "FILTER",
+ "config": {...},
+ "next": {
+ "node_id": "sink-001",
+ "node_name": "写入MySQL",
+ "operator_type": "JDBC_SINK",
+ "config": {...}
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+**优点**:
+- ✅ 数据流向非常清晰
+- ✅ 适合简单的线性流程
+
+**缺点**:
+- ❌ 不支持多分支
+- ❌ 不支持复杂的DAG结构
+
+## 解决方案2:使用可视化标注
+
+在JSON中添加注释和序号:
+
+```json
+{
+ "version": "1.0",
+ "flow_description": "Kafka → Parse → Filter → MySQL",
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "Kafka数据源",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "sequence": 1,
+ "description": "第一步:从Kafka读取数据",
+ "config": {...}
+ },
+ {
+ "node_id": "op-parse-001",
+ "node_name": "解析JSON",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "sequence": 2,
+ "description": "第二步:解析JSON数据,输入来自source-001",
+ "config": {...}
+ },
+ {
+ "node_id": "op-filter-001",
+ "node_name": "过滤",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "sequence": 3,
+ "description": "第三步:过滤有效数据,输入来自op-parse-001",
+ "config": {...}
+ },
+ {
+ "node_id": "sink-001",
+ "node_name": "写入MySQL",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "sequence": 4,
+ "description": "第四步:写入MySQL,输入来自op-filter-001",
+ "config": {...}
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-parse-001",
+ "description": "Kafka数据源 → 解析JSON"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-filter-001",
+ "description": "解析JSON → 过滤"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-filter-001",
+ "target_node_id": "sink-001",
+ "description": "过滤 → 写入MySQL"
+ }
+ ]
+}
+```
+
+## 解决方案3:辅助工具类
+
+提供工具方法快速查询节点关系:
+
+```java
+public class GraphHelper {
+
+ /**
+ * 获取节点的上游节点列表
+ */
+ public static List getUpstreamNodes(String nodeId, StreamGraph graph) {
+ return graph.getEdges().stream()
+ .filter(edge -> edge.getTargetNodeId().equals(nodeId))
+ .map(Edge::getSourceNodeId)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * 获取节点的下游节点列表
+ */
+ public static List getDownstreamNodes(String nodeId, StreamGraph graph) {
+ return graph.getEdges().stream()
+ .filter(edge -> edge.getSourceNodeId().equals(nodeId))
+ .map(Edge::getTargetNodeId)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * 打印节点的上下游关系
+ */
+ public static void printNodeRelations(StreamGraph graph) {
+ graph.getNodes().forEach(node -> {
+ List upstream = getUpstreamNodes(node.getNodeId(), graph);
+ List downstream = getDownstreamNodes(node.getNodeId(), graph);
+
+ System.out.printf("节点: %s (%s)\n", node.getNodeName(), node.getNodeId());
+ System.out.printf(" ← 上游: %s\n", upstream.isEmpty() ? "无" : String.join(", ", upstream));
+ System.out.printf(" → 下游: %s\n", downstream.isEmpty() ? "无" : String.join(", ", downstream));
+ System.out.println();
+ });
+ }
+
+ /**
+ * 生成Mermaid流程图
+ */
+ public static String generateMermaidDiagram(StreamGraph graph) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("graph LR\n");
+
+ // 节点定义
+ graph.getNodes().forEach(node -> {
+ sb.append(String.format(" %s[%s]\n",
+ node.getNodeId(),
+ node.getNodeName()
+ ));
+ });
+
+ // 边定义
+ graph.getEdges().forEach(edge -> {
+ sb.append(String.format(" %s --> %s\n",
+ edge.getSourceNodeId(),
+ edge.getTargetNodeId()
+ ));
+ });
+
+ return sb.toString();
+ }
+}
+```
+
+使用示例:
+
+```java
+// 加载StreamGraph
+StreamGraph graph = loadFromDatabase(graphId);
+
+// 打印节点关系
+GraphHelper.printNodeRelations(graph);
+
+// 输出:
+// 节点: Kafka数据源 (source-001)
+// ← 上游: 无
+// → 下游: op-parse-001
+//
+// 节点: 解析JSON (op-parse-001)
+// ← 上游: source-001
+// → 下游: op-filter-001
+//
+// 节点: 过滤 (op-filter-001)
+// ← 上游: op-parse-001
+// → 下游: sink-001
+//
+// 节点: 写入MySQL (sink-001)
+// ← 上游: op-filter-001
+// → 下游: 无
+
+// 生成可视化图表
+String mermaid = GraphHelper.generateMermaidDiagram(graph);
+System.out.println(mermaid);
+```
+
+## 推荐的最佳实践
+
+### 方案:混合使用(推荐)
+
+**1. JSON中添加辅助信息**
+
+```json
+{
+ "version": "1.0",
+ "metadata": {
+ "name": "用户事件ETL",
+ "description": "从Kafka读取用户事件,解析后写入MySQL",
+ "flow_diagram": "Kafka → Parse → Filter → MySQL"
+ },
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "Kafka数据源",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "position": {"x": 100, "y": 100},
+ "config": {...}
+ },
+ {
+ "node_id": "op-parse-001",
+ "node_name": "解析JSON",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "position": {"x": 300, "y": 100},
+ "config": {...}
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-parse-001",
+ "label": "原始数据"
+ }
+ ]
+}
+```
+
+**2. 数据库表添加辅助字段**
+
+修改`etl_stream_graph`表:
+
+```sql
+ALTER TABLE etl_stream_graph
+ADD COLUMN flow_diagram TEXT COMMENT '流程图描述',
+ADD COLUMN node_relations JSON COMMENT '节点关系映射';
+```
+
+存储时自动生成node_relations:
+
+```json
+{
+ "source-001": {
+ "upstream": [],
+ "downstream": ["op-parse-001"]
+ },
+ "op-parse-001": {
+ "upstream": ["source-001"],
+ "downstream": ["op-filter-001"]
+ },
+ "op-filter-001": {
+ "upstream": ["op-parse-001"],
+ "downstream": ["sink-001"]
+ },
+ "sink-001": {
+ "upstream": ["op-filter-001"],
+ "downstream": []
+ }
+}
+```
+
+**3. 提供可视化界面**
+
+在Web管理界面提供图形化编辑器:
+
+```
+┌─────────────────────────────────────────────┐
+│ ETL任务可视化编辑器 │
+├─────────────────────────────────────────────┤
+│ │
+│ ┌─────────┐ ┌─────────┐ ┌────────┐│
+│ │ Kafka │───▶│ Parse │───▶│ Filter ││
+│ │ Source │ │ JSON │ │ ││
+│ └─────────┘ └─────────┘ └────────┘│
+│ │ │
+│ ▼ │
+│ ┌────────┐│
+│ │ MySQL ││
+│ │ Sink ││
+│ └────────┘│
+│ │
+└─────────────────────────────────────────────┘
+```
+
+## 完整示例:带关系信息的JSON
+
+```json
+{
+ "version": "1.0",
+ "metadata": {
+ "name": "用户事件实时处理",
+ "description": "从Kafka读取用户事件,解析、过滤后写入MySQL",
+ "flow_diagram": "Kafka Source → Parse JSON → Filter Valid → MySQL Sink",
+ "created_by": "admin",
+ "created_at": "2025-11-09T10:00:00Z"
+ },
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "Kafka用户事件源",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "position": {"x": 100, "y": 100},
+ "upstream": [],
+ "downstream": ["op-parse-001"],
+ "config": {
+ "datasource_id": "kafka-prod",
+ "topics": ["user-events"],
+ "group_id": "user-etl"
+ }
+ },
+ {
+ "node_id": "op-parse-001",
+ "node_name": "解析JSON",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "position": {"x": 300, "y": 100},
+ "upstream": ["source-001"],
+ "downstream": ["op-filter-001"],
+ "config": {
+ "function_class": "com.example.ParseJsonFunction"
+ }
+ },
+ {
+ "node_id": "op-filter-001",
+ "node_name": "过滤有效数据",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "position": {"x": 500, "y": 100},
+ "upstream": ["op-parse-001"],
+ "downstream": ["sink-001"],
+ "config": {
+ "predicate_expression": "user_id != null && event_type != null"
+ }
+ },
+ {
+ "node_id": "sink-001",
+ "node_name": "MySQL用户事件表",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "position": {"x": 700, "y": 100},
+ "upstream": ["op-filter-001"],
+ "downstream": [],
+ "config": {
+ "datasource_id": "mysql-warehouse",
+ "table": "user_events",
+ "batch_size": 100
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-parse-001",
+ "label": "原始消息",
+ "description": "从Kafka读取的原始JSON消息"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-filter-001",
+ "label": "解析后数据",
+ "description": "解析后的结构化数据"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-filter-001",
+ "target_node_id": "sink-001",
+ "label": "有效数据",
+ "description": "过滤后的有效用户事件"
+ }
+ ],
+ "global_config": {
+ "buffer_size": 1000,
+ "checkpoint_enabled": true
+ }
+}
+```
+
+## 查询节点关系的SQL
+
+```sql
+-- 查询节点及其上下游关系
+SELECT
+ node_id,
+ node_name,
+ upstream,
+ downstream
+FROM (
+ SELECT
+ node_id,
+ node_name,
+ JSON_EXTRACT(graph_definition, CONCAT('$.nodes[', idx, '].upstream')) as upstream,
+ JSON_EXTRACT(graph_definition, CONCAT('$.nodes[', idx, '].downstream')) as downstream
+ FROM etl_stream_graph,
+ JSON_TABLE(
+ graph_definition,
+ '$.nodes[*]' COLUMNS (
+ idx FOR ORDINALITY,
+ node_id VARCHAR(64) PATH '$.node_id',
+ node_name VARCHAR(128) PATH '$.node_name'
+ )
+ ) AS nodes_table
+ WHERE graph_id = 'your-graph-id'
+) AS node_relations;
+```
+
+## 总结
+
+**最佳方案组合**:
+
+1. ✅ 在nodes中添加`upstream`和`downstream`字段(冗余但直观)
+2. ✅ 保留edges定义(用于详细配置)
+3. ✅ 添加`metadata`和`flow_diagram`(总览描述)
+4. ✅ 添加`position`坐标(用于可视化)
+5. ✅ 在edge中添加`label`和`description`(说明数据流)
+6. ✅ 提供工具类快速查询关系
+7. ✅ 提供Web可视化编辑器
+
+这样既保持了灵活性,又提高了可读性!
+
+---
+
+**文档版本**: v1.0
+**最后更新**: 2025-11-09
diff --git a/docs/graph-definition-json-examples.json b/docs/graph-definition-json-examples.json
new file mode 100644
index 000000000..9c7d5563c
--- /dev/null
+++ b/docs/graph-definition-json-examples.json
@@ -0,0 +1,757 @@
+{
+ "examples": [
+ {
+ "name": "简单ETL - Kafka到MySQL",
+ "description": "从Kafka读取用户事件,解析JSON后写入MySQL",
+ "graph_definition": {
+ "version": "1.0",
+ "nodes": [
+ {
+ "node_id": "source-kafka-001",
+ "node_name": "用户事件源",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "config": {
+ "datasource_id": "kafka-prod",
+ "topics": ["user-events"],
+ "group_id": "user-etl-group",
+ "auto_offset_reset": "latest",
+ "poll_timeout_ms": 1000,
+ "max_poll_records": 500
+ }
+ },
+ {
+ "node_id": "op-map-001",
+ "node_name": "解析JSON",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "config": {
+ "function_class": "com.example.etl.function.ParseJsonFunction",
+ "function_config": {
+ "output_fields": ["user_id", "event_type", "event_time", "properties"]
+ }
+ }
+ },
+ {
+ "node_id": "op-filter-001",
+ "node_name": "过滤有效数据",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "config": {
+ "predicate_expression": "user_id != null && event_type != null"
+ }
+ },
+ {
+ "node_id": "sink-mysql-001",
+ "node_name": "写入MySQL",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "config": {
+ "datasource_id": "mysql-warehouse",
+ "table": "user_events",
+ "write_mode": "INSERT",
+ "batch_size": 100,
+ "flush_interval_ms": 5000
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-kafka-001",
+ "target_node_id": "op-map-001"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-map-001",
+ "target_node_id": "op-filter-001"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-filter-001",
+ "target_node_id": "sink-mysql-001"
+ }
+ ],
+ "global_config": {
+ "buffer_size": 1000,
+ "backpressure_strategy": "BUFFER",
+ "checkpoint_enabled": true,
+ "checkpoint_interval_seconds": 60
+ }
+ }
+ },
+ {
+ "name": "实时统计 - 窗口聚合",
+ "description": "实时统计每5分钟各城市的订单数和金额",
+ "graph_definition": {
+ "version": "1.0",
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "订单事件流",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "config": {
+ "datasource_id": "kafka-prod",
+ "topics": ["order-events"],
+ "group_id": "order-stats-group",
+ "auto_offset_reset": "latest"
+ }
+ },
+ {
+ "node_id": "op-parse-001",
+ "node_name": "解析订单",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "config": {
+ "function_class": "com.example.etl.function.ParseOrderFunction"
+ }
+ },
+ {
+ "node_id": "op-window-001",
+ "node_name": "5分钟滚动窗口",
+ "node_type": "OPERATOR",
+ "operator_type": "WINDOW",
+ "config": {
+ "window_type": "TUMBLING",
+ "window_size": "5m",
+ "allowed_lateness": "1m"
+ }
+ },
+ {
+ "node_id": "op-agg-001",
+ "node_name": "按城市聚合",
+ "node_type": "OPERATOR",
+ "operator_type": "AGGREGATE",
+ "config": {
+ "group_by_fields": ["city"],
+ "aggregations": [
+ {
+ "field": "order_id",
+ "function": "COUNT",
+ "alias": "order_count"
+ },
+ {
+ "field": "amount",
+ "function": "SUM",
+ "alias": "total_amount"
+ },
+ {
+ "field": "amount",
+ "function": "AVG",
+ "alias": "avg_amount"
+ },
+ {
+ "field": "amount",
+ "function": "MAX",
+ "alias": "max_amount"
+ }
+ ]
+ }
+ },
+ {
+ "node_id": "sink-mysql-001",
+ "node_name": "统计结果入库",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "config": {
+ "datasource_id": "mysql-warehouse",
+ "table": "order_stats_5m",
+ "write_mode": "INSERT",
+ "batch_size": 50,
+ "field_mapping": {
+ "stat_time": "window_end",
+ "city_name": "city",
+ "order_cnt": "order_count",
+ "total_amt": "total_amount",
+ "avg_amt": "avg_amount",
+ "max_amt": "max_amount"
+ }
+ }
+ },
+ {
+ "node_id": "sink-redis-001",
+ "node_name": "缓存最新统计",
+ "node_type": "SINK",
+ "operator_type": "REDIS_SINK",
+ "config": {
+ "datasource_id": "redis-cache",
+ "key_pattern": "order:stats:5m:{city}",
+ "value_type": "JSON",
+ "expire_seconds": 3600
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-parse-001"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-window-001"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-window-001",
+ "target_node_id": "op-agg-001"
+ },
+ {
+ "edge_id": "edge-004",
+ "source_node_id": "op-agg-001",
+ "target_node_id": "sink-mysql-001"
+ },
+ {
+ "edge_id": "edge-005",
+ "source_node_id": "op-agg-001",
+ "target_node_id": "sink-redis-001"
+ }
+ ],
+ "global_config": {
+ "buffer_size": 2000,
+ "checkpoint_enabled": true,
+ "checkpoint_interval_seconds": 120
+ }
+ }
+ },
+ {
+ "name": "数据清洗 - 去重和转换",
+ "description": "从数据库读取数据,去重、转换后写入数据仓库",
+ "graph_definition": {
+ "version": "1.0",
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "MySQL增量读取",
+ "node_type": "SOURCE",
+ "operator_type": "JDBC_SOURCE",
+ "config": {
+ "datasource_id": "mysql-app",
+ "query": "SELECT * FROM user_actions WHERE updated_at > ? AND updated_at <= ? ORDER BY updated_at",
+ "fetch_size": 5000,
+ "timestamp_column": "updated_at",
+ "increment_type": "TIME_BASED",
+ "poll_interval_seconds": 60
+ }
+ },
+ {
+ "node_id": "op-dedup-001",
+ "node_name": "去重",
+ "node_type": "OPERATOR",
+ "operator_type": "DEDUPLICATE",
+ "config": {
+ "key_fields": ["user_id", "action_id"],
+ "time_window": "1h",
+ "keep_first": true
+ }
+ },
+ {
+ "node_id": "op-map-001",
+ "node_name": "数据转换",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "config": {
+ "function_class": "com.example.etl.function.TransformUserActionFunction",
+ "function_config": {
+ "add_fields": {
+ "etl_time": "current_timestamp",
+ "source": "mysql-app"
+ }
+ }
+ }
+ },
+ {
+ "node_id": "op-filter-001",
+ "node_name": "过滤测试数据",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "config": {
+ "predicate_expression": "user_id > 100000 && status == 'valid'"
+ }
+ },
+ {
+ "node_id": "sink-001",
+ "node_name": "写入数仓",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "config": {
+ "datasource_id": "mysql-dw",
+ "table": "dw_user_actions",
+ "write_mode": "UPSERT",
+ "unique_key": ["user_id", "action_id"],
+ "batch_size": 1000,
+ "use_transaction": true
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-dedup-001"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-dedup-001",
+ "target_node_id": "op-map-001"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-map-001",
+ "target_node_id": "op-filter-001"
+ },
+ {
+ "edge_id": "edge-004",
+ "source_node_id": "op-filter-001",
+ "target_node_id": "sink-001"
+ }
+ ],
+ "global_config": {
+ "buffer_size": 5000,
+ "checkpoint_enabled": true,
+ "checkpoint_interval_seconds": 300
+ }
+ }
+ },
+ {
+ "name": "多分支处理 - 日志分流",
+ "description": "读取日志流,按类型分流到不同的存储",
+ "graph_definition": {
+ "version": "1.0",
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "应用日志流",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "config": {
+ "datasource_id": "kafka-prod",
+ "topics": ["app-logs"],
+ "group_id": "log-processor-group"
+ }
+ },
+ {
+ "node_id": "op-parse-001",
+ "node_name": "解析日志",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "config": {
+ "function_class": "com.example.etl.function.ParseLogFunction"
+ }
+ },
+ {
+ "node_id": "op-filter-error-001",
+ "node_name": "过滤ERROR日志",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "config": {
+ "predicate_expression": "level == 'ERROR'"
+ }
+ },
+ {
+ "node_id": "op-filter-warn-001",
+ "node_name": "过滤WARN日志",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "config": {
+ "predicate_expression": "level == 'WARN'"
+ }
+ },
+ {
+ "node_id": "op-filter-info-001",
+ "node_name": "过滤INFO日志",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "config": {
+ "predicate_expression": "level == 'INFO'"
+ }
+ },
+ {
+ "node_id": "sink-error-001",
+ "node_name": "ERROR日志告警",
+ "node_type": "SINK",
+ "operator_type": "HTTP_SINK",
+ "config": {
+ "url": "https://alert.example.com/api/send",
+ "method": "POST",
+ "headers": {
+ "Content-Type": "application/json",
+ "Authorization": "Bearer ${alert_token}"
+ },
+ "batch_size": 10,
+ "timeout_seconds": 5
+ }
+ },
+ {
+ "node_id": "sink-warn-001",
+ "node_name": "WARN日志入库",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "config": {
+ "datasource_id": "mysql-log",
+ "table": "warn_logs",
+ "batch_size": 100
+ }
+ },
+ {
+ "node_id": "sink-all-001",
+ "node_name": "全量日志存储",
+ "node_type": "SINK",
+ "operator_type": "ELASTICSEARCH_SINK",
+ "config": {
+ "datasource_id": "es-log-cluster",
+ "index": "app_logs_{date}",
+ "id_field": "log_id",
+ "batch_size": 500,
+ "flush_interval_ms": 3000
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-parse-001"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-filter-error-001"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-filter-warn-001"
+ },
+ {
+ "edge_id": "edge-004",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-filter-info-001"
+ },
+ {
+ "edge_id": "edge-005",
+ "source_node_id": "op-filter-error-001",
+ "target_node_id": "sink-error-001"
+ },
+ {
+ "edge_id": "edge-006",
+ "source_node_id": "op-filter-warn-001",
+ "target_node_id": "sink-warn-001"
+ },
+ {
+ "edge_id": "edge-007",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "sink-all-001"
+ }
+ ],
+ "global_config": {
+ "buffer_size": 3000,
+ "backpressure_strategy": "DROP_OLDEST",
+ "checkpoint_enabled": true,
+ "checkpoint_interval_seconds": 180
+ }
+ }
+ },
+ {
+ "name": "API数据采集",
+ "description": "定期从HTTP API拉取数据并存储",
+ "graph_definition": {
+ "version": "1.0",
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "API数据源",
+ "node_type": "SOURCE",
+ "operator_type": "HTTP_SOURCE",
+ "config": {
+ "url": "https://api.example.com/v1/users",
+ "method": "GET",
+ "headers": {
+ "Authorization": "Bearer ${api_token}",
+ "Accept": "application/json"
+ },
+ "query_params": {
+ "page_size": "1000",
+ "updated_after": "${last_updated_time}"
+ },
+ "poll_interval_seconds": 300,
+ "timeout_seconds": 30,
+ "retry_times": 3
+ }
+ },
+ {
+ "node_id": "op-flatmap-001",
+ "node_name": "展开数组",
+ "node_type": "OPERATOR",
+ "operator_type": "FLATMAP",
+ "config": {
+ "function_class": "com.example.etl.function.FlattenArrayFunction",
+ "source_field": "data.users"
+ }
+ },
+ {
+ "node_id": "op-map-001",
+ "node_name": "字段映射",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "config": {
+ "function_class": "com.example.etl.function.MapFieldsFunction",
+ "field_mapping": {
+ "id": "user_id",
+ "name": "user_name",
+ "email": "user_email",
+ "created_at": "create_time",
+ "updated_at": "update_time"
+ }
+ }
+ },
+ {
+ "node_id": "sink-001",
+ "node_name": "写入MySQL",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "config": {
+ "datasource_id": "mysql-user",
+ "table": "users",
+ "write_mode": "UPSERT",
+ "unique_key": ["user_id"],
+ "batch_size": 200
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-flatmap-001"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-flatmap-001",
+ "target_node_id": "op-map-001"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-map-001",
+ "target_node_id": "sink-001"
+ }
+ ],
+ "global_config": {
+ "buffer_size": 1000,
+ "checkpoint_enabled": false
+ }
+ }
+ },
+ {
+ "name": "文件处理 - CSV到JSON",
+ "description": "读取CSV文件,转换为JSON后写入Kafka",
+ "graph_definition": {
+ "version": "1.0",
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "CSV文件源",
+ "node_type": "SOURCE",
+ "operator_type": "FILE_SOURCE",
+ "config": {
+ "path": "/data/input/*.csv",
+ "format": "CSV",
+ "charset": "UTF-8",
+ "delimiter": ",",
+ "has_header": true,
+ "watch_mode": "CONTINUOUS",
+ "scan_interval_seconds": 30,
+ "file_filter": "user_export_*.csv"
+ }
+ },
+ {
+ "node_id": "op-map-001",
+ "node_name": "转换为JSON",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "config": {
+ "function_class": "com.example.etl.function.CsvToJsonFunction",
+ "function_config": {
+ "include_metadata": true,
+ "timestamp_format": "yyyy-MM-dd HH:mm:ss"
+ }
+ }
+ },
+ {
+ "node_id": "op-filter-001",
+ "node_name": "过滤空行",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "config": {
+ "predicate_expression": "row_data != null && row_data.trim() != ''"
+ }
+ },
+ {
+ "node_id": "sink-kafka-001",
+ "node_name": "写入Kafka",
+ "node_type": "SINK",
+ "operator_type": "KAFKA_SINK",
+ "config": {
+ "datasource_id": "kafka-prod",
+ "topic": "user-import",
+ "key_field": "user_id",
+ "serialization": "JSON",
+ "compression": "gzip",
+ "batch_size": 100
+ }
+ },
+ {
+ "node_id": "sink-file-001",
+ "node_name": "归档JSON文件",
+ "node_type": "SINK",
+ "operator_type": "FILE_SINK",
+ "config": {
+ "path": "/data/archive/users_{date}.json",
+ "format": "JSON",
+ "charset": "UTF-8",
+ "rolling_policy": {
+ "type": "SIZE",
+ "max_size_mb": 100
+ },
+ "compression": "gzip"
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-map-001"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-map-001",
+ "target_node_id": "op-filter-001"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-filter-001",
+ "target_node_id": "sink-kafka-001"
+ },
+ {
+ "edge_id": "edge-004",
+ "source_node_id": "op-filter-001",
+ "target_node_id": "sink-file-001"
+ }
+ ],
+ "global_config": {
+ "buffer_size": 2000,
+ "checkpoint_enabled": true,
+ "checkpoint_interval_seconds": 300
+ }
+ }
+ },
+ {
+ "name": "数据关联 - JOIN操作",
+ "description": "订单流关联用户信息和商品信息",
+ "graph_definition": {
+ "version": "1.0",
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "订单流",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "config": {
+ "datasource_id": "kafka-prod",
+ "topics": ["orders"],
+ "group_id": "order-enrich-group"
+ }
+ },
+ {
+ "node_id": "op-parse-001",
+ "node_name": "解析订单",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "config": {
+ "function_class": "com.example.etl.function.ParseOrderFunction"
+ }
+ },
+ {
+ "node_id": "op-join-user-001",
+ "node_name": "关联用户信息",
+ "node_type": "OPERATOR",
+ "operator_type": "JOIN",
+ "config": {
+ "join_type": "LEFT",
+ "left_key": "user_id",
+ "right_key": "id",
+ "right_source": {
+ "type": "JDBC",
+ "datasource_id": "mysql-user",
+ "query": "SELECT id, name, city, vip_level FROM users WHERE id IN (?)",
+ "cache_enabled": true,
+ "cache_ttl_seconds": 300,
+ "cache_max_size": 10000
+ },
+ "output_fields": ["*", "user.name as user_name", "user.city as user_city", "user.vip_level"]
+ }
+ },
+ {
+ "node_id": "op-join-product-001",
+ "node_name": "关联商品信息",
+ "node_type": "OPERATOR",
+ "operator_type": "JOIN",
+ "config": {
+ "join_type": "LEFT",
+ "left_key": "product_id",
+ "right_key": "id",
+ "right_source": {
+ "type": "REDIS",
+ "datasource_id": "redis-cache",
+ "key_pattern": "product:info:{product_id}"
+ },
+ "output_fields": ["*", "product.name as product_name", "product.category", "product.price"]
+ }
+ },
+ {
+ "node_id": "sink-001",
+ "node_name": "写入ES",
+ "node_type": "SINK",
+ "operator_type": "ELASTICSEARCH_SINK",
+ "config": {
+ "datasource_id": "es-order-cluster",
+ "index": "order_detail_{date}",
+ "id_field": "order_id",
+ "batch_size": 200
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-parse-001"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-join-user-001"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-join-user-001",
+ "target_node_id": "op-join-product-001"
+ },
+ {
+ "edge_id": "edge-004",
+ "source_node_id": "op-join-product-001",
+ "target_node_id": "sink-001"
+ }
+ ],
+ "global_config": {
+ "buffer_size": 1500,
+ "checkpoint_enabled": true,
+ "checkpoint_interval_seconds": 120
+ }
+ }
+ }
+ ]
+}
diff --git a/docs/graph-example-with-relations.json b/docs/graph-example-with-relations.json
new file mode 100644
index 000000000..3be6f7fca
--- /dev/null
+++ b/docs/graph-example-with-relations.json
@@ -0,0 +1,233 @@
+{
+ "简单示例_带关系信息": {
+ "version": "1.0",
+ "metadata": {
+ "name": "用户事件ETL",
+ "flow_diagram": "Kafka → Parse → Filter → MySQL",
+ "description": "从Kafka读取用户事件,解析JSON后过滤,写入MySQL"
+ },
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "Kafka数据源",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "upstream": [],
+ "downstream": ["op-parse-001"],
+ "description": "【第1步】从Kafka读取原始数据 → 发送给 op-parse-001",
+ "config": {
+ "datasource_id": "kafka-prod",
+ "topics": ["user-events"],
+ "group_id": "user-etl"
+ }
+ },
+ {
+ "node_id": "op-parse-001",
+ "node_name": "解析JSON",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "upstream": ["source-001"],
+ "downstream": ["op-filter-001"],
+ "description": "【第2步】接收 source-001 的数据,解析JSON → 发送给 op-filter-001",
+ "config": {
+ "function_class": "com.example.ParseJsonFunction"
+ }
+ },
+ {
+ "node_id": "op-filter-001",
+ "node_name": "过滤有效数据",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "upstream": ["op-parse-001"],
+ "downstream": ["sink-001"],
+ "description": "【第3步】接收 op-parse-001 的数据,过滤 → 发送给 sink-001",
+ "config": {
+ "predicate_expression": "user_id != null && event_type != null"
+ }
+ },
+ {
+ "node_id": "sink-001",
+ "node_name": "写入MySQL",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "upstream": ["op-filter-001"],
+ "downstream": [],
+ "description": "【第4步】接收 op-filter-001 的数据,写入MySQL",
+ "config": {
+ "datasource_id": "mysql-warehouse",
+ "table": "user_events",
+ "batch_size": 100
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-parse-001",
+ "label": "原始JSON消息"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-filter-001",
+ "label": "解析后的对象"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-filter-001",
+ "target_node_id": "sink-001",
+ "label": "有效数据"
+ }
+ ]
+ },
+ "多分支示例_带关系信息": {
+ "version": "1.0",
+ "metadata": {
+ "name": "日志分流处理",
+ "flow_diagram": "Kafka → Parse → [ERROR→HTTP, WARN→MySQL, ALL→ES]",
+ "description": "读取日志流,按级别分流到不同存储"
+ },
+ "nodes": [
+ {
+ "node_id": "source-001",
+ "node_name": "日志流",
+ "node_type": "SOURCE",
+ "operator_type": "KAFKA_SOURCE",
+ "upstream": [],
+ "downstream": ["op-parse-001"],
+ "description": "【第1步】从Kafka读取日志 → 发送给 op-parse-001",
+ "config": {
+ "datasource_id": "kafka-prod",
+ "topics": ["app-logs"]
+ }
+ },
+ {
+ "node_id": "op-parse-001",
+ "node_name": "解析日志",
+ "node_type": "OPERATOR",
+ "operator_type": "MAP",
+ "upstream": ["source-001"],
+ "downstream": ["op-filter-error-001", "op-filter-warn-001", "sink-es-001"],
+ "description": "【第2步】接收 source-001 的数据,解析 → 分发给3个下游节点",
+ "config": {
+ "function_class": "com.example.ParseLogFunction"
+ }
+ },
+ {
+ "node_id": "op-filter-error-001",
+ "node_name": "过滤ERROR",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "upstream": ["op-parse-001"],
+ "downstream": ["sink-http-001"],
+ "description": "【第3步-分支1】接收 op-parse-001 的数据,过滤ERROR → 发送给 sink-http-001",
+ "config": {
+ "predicate_expression": "level == 'ERROR'"
+ }
+ },
+ {
+ "node_id": "op-filter-warn-001",
+ "node_name": "过滤WARN",
+ "node_type": "OPERATOR",
+ "operator_type": "FILTER",
+ "upstream": ["op-parse-001"],
+ "downstream": ["sink-mysql-001"],
+ "description": "【第3步-分支2】接收 op-parse-001 的数据,过滤WARN → 发送给 sink-mysql-001",
+ "config": {
+ "predicate_expression": "level == 'WARN'"
+ }
+ },
+ {
+ "node_id": "sink-http-001",
+ "node_name": "告警API",
+ "node_type": "SINK",
+ "operator_type": "HTTP_SINK",
+ "upstream": ["op-filter-error-001"],
+ "downstream": [],
+ "description": "【第4步-分支1】接收 op-filter-error-001 的数据,发送告警",
+ "config": {
+ "url": "https://alert.example.com/api/send"
+ }
+ },
+ {
+ "node_id": "sink-mysql-001",
+ "node_name": "WARN日志表",
+ "node_type": "SINK",
+ "operator_type": "JDBC_SINK",
+ "upstream": ["op-filter-warn-001"],
+ "downstream": [],
+ "description": "【第4步-分支2】接收 op-filter-warn-001 的数据,写入MySQL",
+ "config": {
+ "datasource_id": "mysql-log",
+ "table": "warn_logs"
+ }
+ },
+ {
+ "node_id": "sink-es-001",
+ "node_name": "全量日志ES",
+ "node_type": "SINK",
+ "operator_type": "ELASTICSEARCH_SINK",
+ "upstream": ["op-parse-001"],
+ "downstream": [],
+ "description": "【第3步-分支3】接收 op-parse-001 的全量数据,写入ES",
+ "config": {
+ "datasource_id": "es-log",
+ "index": "app_logs_{date}"
+ }
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "edge-001",
+ "source_node_id": "source-001",
+ "target_node_id": "op-parse-001",
+ "label": "原始日志"
+ },
+ {
+ "edge_id": "edge-002",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-filter-error-001",
+ "label": "所有日志(分支1)"
+ },
+ {
+ "edge_id": "edge-003",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "op-filter-warn-001",
+ "label": "所有日志(分支2)"
+ },
+ {
+ "edge_id": "edge-004",
+ "source_node_id": "op-parse-001",
+ "target_node_id": "sink-es-001",
+ "label": "所有日志(分支3)"
+ },
+ {
+ "edge_id": "edge-005",
+ "source_node_id": "op-filter-error-001",
+ "target_node_id": "sink-http-001",
+ "label": "ERROR日志"
+ },
+ {
+ "edge_id": "edge-006",
+ "source_node_id": "op-filter-warn-001",
+ "target_node_id": "sink-mysql-001",
+ "label": "WARN日志"
+ }
+ ]
+ },
+ "如何阅读": {
+ "说明": "每个节点都包含upstream和downstream字段,可以直接看出上下游关系",
+ "upstream": "当前节点的数据来自哪些节点(数组)",
+ "downstream": "当前节点的数据发送给哪些节点(数组)",
+ "description": "用中文描述了数据流向,更容易理解",
+ "示例": {
+ "节点定义": {
+ "node_id": "op-parse-001",
+ "upstream": ["source-001"],
+ "downstream": ["op-filter-001"],
+ "含义": "这个节点从source-001接收数据,处理后发送给op-filter-001"
+ }
+ }
+ }
+}
diff --git a/docs/json-examples-guide.md b/docs/json-examples-guide.md
new file mode 100644
index 000000000..412cc4f4a
--- /dev/null
+++ b/docs/json-examples-guide.md
@@ -0,0 +1,386 @@
+# StreamGraph JSON配置示例指南
+
+## 概述
+
+本文档提供了7个完整的、可直接使用的StreamGraph JSON配置示例,涵盖常见的ETL场景。
+
+完整的JSON文件位于:`graph-definition-json-examples.json`
+
+## 示例列表
+
+### 1. 简单ETL - Kafka到MySQL
+
+**场景**: 从Kafka读取用户事件,解析JSON后写入MySQL
+
+**数据流程**:
+```
+Kafka Source → Parse JSON → Filter → MySQL Sink
+```
+
+**适用场景**:
+- 基础数据采集
+- 消息队列到数据库同步
+- 实时数据入库
+
+**关键配置**:
+```json
+{
+ "source": "KAFKA_SOURCE",
+ "operators": ["MAP", "FILTER"],
+ "sink": "JDBC_SINK"
+}
+```
+
+---
+
+### 2. 实时统计 - 窗口聚合
+
+**场景**: 实时统计每5分钟各城市的订单数和金额
+
+**数据流程**:
+```
+Kafka Source → Parse → Window(5m) → Aggregate → MySQL + Redis
+```
+
+**适用场景**:
+- 实时监控大屏
+- 业务指标统计
+- 实时报表
+
+**特点**:
+- ✅ 有状态计算(Window + Aggregate)
+- ✅ 多Sink输出(数据库 + 缓存)
+- ✅ 支持检查点容错
+
+**聚合函数**:
+- COUNT: 订单数量
+- SUM: 总金额
+- AVG: 平均金额
+- MAX: 最大金额
+
+---
+
+### 3. 数据清洗 - 去重和转换
+
+**场景**: 从数据库读取数据,去重、转换后写入数据仓库
+
+**数据流程**:
+```
+JDBC Source → Deduplicate → Transform → Filter → JDBC Sink
+```
+
+**适用场景**:
+- 数据同步
+- 离线数据处理
+- 数据仓库ETL
+
+**特点**:
+- ✅ 增量读取(基于时间戳)
+- ✅ 去重操作(DEDUPLICATE)
+- ✅ UPSERT写入模式
+- ✅ 事务支持
+
+---
+
+### 4. 多分支处理 - 日志分流
+
+**场景**: 读取日志流,按日志级别分流到不同的存储
+
+**数据流程**:
+```
+ ┌→ Filter(ERROR) → HTTP Alert
+Kafka Source ────┼→ Filter(WARN) → MySQL
+ └→ All Logs → Elasticsearch
+```
+
+**适用场景**:
+- 日志分析
+- 告警系统
+- 日志归档
+
+**特点**:
+- ✅ 一个Source多个Sink
+- ✅ 条件分支处理
+- ✅ 不同级别不同处理策略
+
+---
+
+### 5. API数据采集
+
+**场景**: 定期从HTTP API拉取数据并存储
+
+**数据流程**:
+```
+HTTP Source → FlatMap → Map → JDBC Sink
+```
+
+**适用场景**:
+- 第三方API数据同步
+- 定时数据拉取
+- 外部数据集成
+
+**特点**:
+- ✅ 周期性拉取(poll_interval)
+- ✅ 数组展开(FlatMap)
+- ✅ 字段映射
+- ✅ 重试机制
+
+---
+
+### 6. 文件处理 - CSV到JSON
+
+**场景**: 读取CSV文件,转换为JSON后写入Kafka和归档
+
+**数据流程**:
+```
+ ┌→ Kafka Sink
+File Source → Map ─┤
+ └→ File Sink (JSON)
+```
+
+**适用场景**:
+- 文件导入
+- 数据格式转换
+- 批量数据处理
+
+**特点**:
+- ✅ 文件监控(watch_mode)
+- ✅ CSV解析
+- ✅ 多目标输出
+- ✅ 文件归档
+
+---
+
+### 7. 数据关联 - JOIN操作
+
+**场景**: 订单流关联用户信息和商品信息
+
+**数据流程**:
+```
+Kafka Source → Parse → Join(User) → Join(Product) → ES Sink
+```
+
+**适用场景**:
+- 数据补全
+- 维度关联
+- 实时宽表
+
+**特点**:
+- ✅ 多次JOIN操作
+- ✅ 支持缓存(提高性能)
+- ✅ 从MySQL/Redis读取维度数据
+- ✅ 字段别名
+
+---
+
+## 如何使用这些示例
+
+### 方法1: 直接插入数据库
+
+```sql
+-- 插入StreamGraph
+INSERT INTO etl_stream_graph (graph_id, graph_name, job_id, graph_definition)
+VALUES (
+ 'graph-001',
+ '简单ETL任务',
+ 'job-001',
+ '这里粘贴完整的graph_definition JSON'
+);
+```
+
+### 方法2: 通过API创建
+
+```bash
+curl -X POST http://localhost:8080/api/stream-graphs \
+ -H "Content-Type: application/json" \
+ -d @graph-definition-json-examples.json
+```
+
+### 方法3: 使用可视化界面
+
+1. 登录Web管理界面
+2. 点击"创建任务"
+3. 选择"导入JSON"
+4. 粘贴对应的graph_definition
+5. 保存并提交
+
+## 配置说明
+
+### 常用配置项
+
+#### Source配置
+```json
+{
+ "datasource_id": "数据源ID(在etl_datasource表中)",
+ "topics": ["Kafka主题列表"],
+ "group_id": "消费者组ID",
+ "poll_interval_seconds": "轮询间隔(秒)"
+}
+```
+
+#### Operator配置
+```json
+{
+ "function_class": "自定义函数类全限定名",
+ "predicate_expression": "过滤条件表达式",
+ "group_by_fields": ["分组字段"],
+ "window_size": "窗口大小(如5m、1h)"
+}
+```
+
+#### Sink配置
+```json
+{
+ "datasource_id": "目标数据源ID",
+ "table": "目标表名",
+ "batch_size": 100,
+ "write_mode": "INSERT/UPSERT/UPDATE"
+}
+```
+
+### 全局配置
+
+```json
+{
+ "buffer_size": 1000,
+ "backpressure_strategy": "BUFFER/DROP/ERROR",
+ "checkpoint_enabled": true,
+ "checkpoint_interval_seconds": 60
+}
+```
+
+## 节点类型速查
+
+| 节点类型 | operator_type | 说明 |
+| --- | --- | --- |
+| Source | KAFKA_SOURCE | Kafka数据源 |
+| Source | JDBC_SOURCE | 数据库数据源 |
+| Source | HTTP_SOURCE | HTTP API数据源 |
+| Source | FILE_SOURCE | 文件数据源 |
+| Operator | MAP | 一对一转换 |
+| Operator | FILTER | 数据过滤 |
+| Operator | FLATMAP | 一对多转换 |
+| Operator | AGGREGATE | 聚合计算 |
+| Operator | WINDOW | 窗口计算 |
+| Operator | JOIN | 数据关联 |
+| Operator | DEDUPLICATE | 数据去重 |
+| Sink | JDBC_SINK | 数据库写入 |
+| Sink | KAFKA_SINK | Kafka写入 |
+| Sink | ELASTICSEARCH_SINK | ES写入 |
+| Sink | FILE_SINK | 文件写入 |
+| Sink | REDIS_SINK | Redis写入 |
+| Sink | HTTP_SINK | HTTP API写入 |
+
+## 配置模板
+
+### 最小配置(必填字段)
+
+```json
+{
+ "version": "1.0",
+ "nodes": [
+ {
+ "node_id": "必填-唯一标识",
+ "node_name": "必填-显示名称",
+ "node_type": "必填-SOURCE/OPERATOR/SINK",
+ "operator_type": "必填-具体算子类型",
+ "config": {}
+ }
+ ],
+ "edges": [
+ {
+ "edge_id": "必填-唯一标识",
+ "source_node_id": "必填-源节点ID",
+ "target_node_id": "必填-目标节点ID"
+ }
+ ]
+}
+```
+
+### 完整配置(包含可选字段)
+
+```json
+{
+ "version": "1.0",
+ "nodes": [...],
+ "edges": [...],
+ "global_config": {
+ "buffer_size": 1000,
+ "backpressure_strategy": "BUFFER",
+ "checkpoint_enabled": true,
+ "checkpoint_interval_seconds": 60,
+ "restart_on_failure": true,
+ "max_restart_attempts": 3,
+ "error_handling": {
+ "on_source_error": "RETRY",
+ "on_operator_error": "SKIP",
+ "on_sink_error": "FAIL"
+ }
+ }
+}
+```
+
+## 常见问题
+
+### Q1: 如何添加自定义算子?
+
+修改nodes中的operator配置:
+```json
+{
+ "operator_type": "MAP",
+ "config": {
+ "function_class": "com.yourcompany.YourCustomFunction",
+ "function_config": {
+ "param1": "value1"
+ }
+ }
+}
+```
+
+### Q2: 如何实现一个Source多个Sink?
+
+添加多个edge指向不同的Sink:
+```json
+{
+ "edges": [
+ {"source_node_id": "op-001", "target_node_id": "sink-001"},
+ {"source_node_id": "op-001", "target_node_id": "sink-002"},
+ {"source_node_id": "op-001", "target_node_id": "sink-003"}
+ ]
+}
+```
+
+### Q3: 如何配置检查点?
+
+在global_config中设置:
+```json
+{
+ "global_config": {
+ "checkpoint_enabled": true,
+ "checkpoint_interval_seconds": 60
+ }
+}
+```
+
+### Q4: 数据源ID在哪里配置?
+
+数据源需要先在`etl_datasource`表中创建,然后在配置中引用其datasource_id。
+
+### Q5: 如何调试配置?
+
+1. 使用JSON验证工具检查语法
+2. 先创建简单的任务测试
+3. 查看任务执行日志
+4. 使用监控指标分析性能
+
+## 下一步
+
+- 查看完整的JSON文件:`graph-definition-json-examples.json`
+- 阅读详细的配置说明:`graph-definition-examples.md`
+- 参考数据库设计文档:`database-design.md`
+- 查看系统设计文档:`reactive-etl-framework-design.md`
+
+---
+
+**文档版本**: v1.0
+**最后更新**: 2025-11-09
diff --git a/docs/reactive-etl-framework-design.md b/docs/reactive-etl-framework-design.md
new file mode 100644
index 000000000..d71660710
--- /dev/null
+++ b/docs/reactive-etl-framework-design.md
@@ -0,0 +1,1501 @@
+# 响应式ETL框架设计文档
+
+## 1. 概述
+
+### 1.1 项目背景
+
+本项目旨在设计并实现一个基于响应式编程模型的轻量级ETL(Extract-Transform-Load)数据采集框架。该框架借鉴Apache Flink的设计理念,采用Source、Operator、Sink的经典数据处理模型,并基于Project Reactor实现完全响应式的数据流处理。
+
+### 1.2 设计目标
+
+- **响应式流处理**:基于Reactor实现非阻塞、背压支持的数据流处理
+- **模块化设计**:清晰的任务调度、图转换、执行引擎分层架构
+- **高性能**:充分利用响应式编程的优势,支持高吞吐量数据处理
+- **易用性**:提供简洁的API,支持声明式任务定义
+- **可观测性**:内置监控指标和日志,方便运维调试
+- **可扩展性**:基于Connectors的插件化扩展机制
+
+### 1.3 核心特性
+
+- 声明式任务定义(StreamGraph → JobGraph转换)
+- 灵活的任务调度机制(Job Scheduler)
+- 高效的执行引擎(Job Executor)
+- 丰富的连接器生态(Connectors)
+- 内置背压机制,防止内存溢出
+- 支持有状态计算和检查点容错
+
+## 2. 系统架构
+
+### 2.1 整体架构图
+
+```mermaid
+graph TB
+ subgraph "User API Layer"
+ API[Stream API]
+ DSL[Job DSL]
+ end
+
+ subgraph "Job Definition Layer"
+ SG[StreamGraph]
+ JG[JobGraph]
+ end
+
+ subgraph "Scheduling Layer"
+ JS[Job Scheduler]
+ JM[Job Manager]
+ end
+
+ subgraph "Execution Layer"
+ JE[Job Executor]
+ RT[Reactor Runtime]
+ end
+
+ subgraph "Operator Layer"
+ SRC[Source]
+ OPS[Operators]
+ SNK[Sink]
+ end
+
+ subgraph "Connector Layer"
+ JDBC[JDBC Connector]
+ KAFKA[Kafka Connector]
+ HTTP[HTTP Connector]
+ FILE[File Connector]
+ CUSTOM[Custom Connectors]
+ end
+
+ subgraph "Infrastructure Layer"
+ SM[State Manager]
+ CP[Checkpoint Manager]
+ MT[Metrics Collector]
+ end
+
+ API --> SG
+ DSL --> SG
+ SG --> JG
+ JG --> JS
+ JS --> JM
+ JM --> JE
+ JE --> RT
+ RT --> SRC
+ RT --> OPS
+ RT --> SNK
+
+ SRC -.-> JDBC
+ SRC -.-> KAFKA
+ SRC -.-> HTTP
+ SRC -.-> FILE
+ SNK -.-> JDBC
+ SNK -.-> KAFKA
+ SNK -.-> HTTP
+ SNK -.-> FILE
+
+ JDBC -.-> CUSTOM
+ KAFKA -.-> CUSTOM
+
+ OPS -.-> SM
+ SM -.-> CP
+ JE -.-> MT
+```
+
+### 2.2 架构分层说明
+
+#### 2.2.1 用户API层(User API Layer)
+提供友好的编程接口,允许用户通过流式API或DSL定义ETL任务。
+
+#### 2.2.2 任务定义层(Job Definition Layer)
+- **StreamGraph**:用户定义的逻辑执行图,描述数据流转换关系
+- **JobGraph**:优化后的物理执行图,可实际调度执行
+
+#### 2.2.3 调度层(Scheduling Layer)
+- **Job Scheduler**:负责任务的调度策略(立即执行、定时执行、依赖触发等)
+- **Job Manager**:管理任务的生命周期(创建、启动、停止、重启)
+
+#### 2.2.4 执行层(Execution Layer)
+- **Job Executor**:任务的实际执行引擎
+- **Reactor Runtime**:响应式运行时环境
+
+#### 2.2.5 算子层(Operator Layer)
+核心的数据处理组件,包括Source、Operator、Sink。
+
+#### 2.2.6 连接器层(Connector Layer)
+提供与各种外部系统交互的能力,采用插件化设计。
+
+#### 2.2.7 基础设施层(Infrastructure Layer)
+提供状态管理、检查点、监控等基础能力。
+
+### 2.3 模块依赖关系图
+
+```mermaid
+graph LR
+ Job --> StreamGraph
+ StreamGraph --> JobGraph
+ JobGraph --> JobScheduler
+ JobScheduler --> JobExecutor
+ JobExecutor --> Source
+ JobExecutor --> Operator
+ JobExecutor --> Sink
+ Source --> Connectors
+ Sink --> Connectors
+ Operator --> StateManager
+ StateManager --> CheckpointManager
+```
+
+## 3. 核心模块设计
+
+### 3.1 Job模块
+
+#### 3.1.1 设计理念
+
+Job是ETL任务的最小执行单元,封装了完整的数据处理逻辑。每个Job包含唯一标识、配置信息、执行状态等元数据。
+
+#### 3.1.2 Job生命周期
+
+```mermaid
+stateDiagram-v2
+ [*] --> CREATED: create()
+ CREATED --> SCHEDULED: schedule()
+ SCHEDULED --> RUNNING: start()
+ RUNNING --> PAUSED: pause()
+ PAUSED --> RUNNING: resume()
+ RUNNING --> COMPLETED: success
+ RUNNING --> FAILED: error
+ FAILED --> RUNNING: retry()
+ RUNNING --> CANCELLED: cancel()
+ COMPLETED --> [*]
+ FAILED --> [*]
+ CANCELLED --> [*]
+```
+
+#### 3.1.3 Job元数据结构
+
+```java
+public class Job {
+ private String jobId; // 任务唯一标识
+ private String jobName; // 任务名称
+ private JobType jobType; // 任务类型:STREAMING/BATCH
+ private JobStatus status; // 任务状态
+ private JobConfig config; // 任务配置
+ private JobGraph jobGraph; // 执行图
+ private Instant createTime; // 创建时间
+ private Instant startTime; // 启动时间
+ private Instant endTime; // 结束时间
+ private Map metadata; // 扩展元数据
+}
+```
+
+### 3.2 StreamGraph模块
+
+#### 3.2.1 设计理念
+
+StreamGraph是用户定义的逻辑执行图,直接映射用户的API调用。它是一个有向无环图(DAG),节点代表算子,边代表数据流向。
+
+#### 3.2.2 StreamGraph结构
+
+```mermaid
+graph LR
+ SN1[Source Node] --> TN1[Transform Node 1]
+ TN1 --> TN2[Transform Node 2]
+ TN1 --> TN3[Transform Node 3]
+ TN2 --> TN4[Transform Node 4]
+ TN3 --> TN4
+ TN4 --> SK1[Sink Node]
+```
+
+#### 3.2.3 StreamNode定义
+
+```java
+public class StreamNode {
+ private int nodeId; // 节点ID
+ private String operatorName; // 算子名称
+ private OperatorType operatorType; // 算子类型
+ private List inEdges; // 输入边
+ private List outEdges; // 输出边
+ private int parallelism; // 并行度
+ private Map config; // 节点配置
+}
+```
+
+#### 3.2.4 StreamGraph构建
+
+用户通过流式API构建StreamGraph:
+
+```java
+StreamGraph graph = StreamGraph.builder()
+ .addSource("source-1", new KafkaSource(config))
+ .addOperator("map-1", new MapOperator(mapper))
+ .addOperator("filter-1", new FilterOperator(predicate))
+ .addSink("sink-1", new JdbcSink(config))
+ .connect("source-1", "map-1")
+ .connect("map-1", "filter-1")
+ .connect("filter-1", "sink-1")
+ .build();
+```
+
+### 3.3 JobGraph模块
+
+#### 3.3.1 设计理念
+
+JobGraph是StreamGraph经过优化后的物理执行图。它将可以链接的算子进行合并(Operator Chain),减少序列化开销,并确定资源分配策略。
+
+#### 3.3.2 StreamGraph到JobGraph的转换
+
+```mermaid
+graph TB
+ subgraph "StreamGraph"
+ SN1[Source] --> SN2[Map]
+ SN2 --> SN3[Filter]
+ SN3 --> SN4[Sink]
+ end
+
+ subgraph "JobGraph Optimization"
+ OPT1[Chain Detection]
+ OPT2[Resource Allocation]
+ OPT3[Parallelism Config]
+ end
+
+ subgraph "JobGraph"
+ JV1[Job Vertex 1
Source→Map→Filter]
+ JV2[Job Vertex 2
Sink]
+ JV1 --> JV2
+ end
+
+ SN1 --> OPT1
+ OPT1 --> OPT2
+ OPT2 --> OPT3
+ OPT3 --> JV1
+```
+
+#### 3.3.3 Operator Chain优化
+
+将满足以下条件的算子链接成一个执行单元:
+- 上下游算子的并行度相同
+- 下游算子只有一个输入
+- 上游算子只有一个输出
+- 两个算子的数据传输策略为FORWARD
+
+#### 3.3.4 JobVertex定义
+
+```java
+public class JobVertex {
+ private int vertexId; // 顶点ID
+ private String vertexName; // 顶点名称
+ private List chainedNodes; // 链接的节点列表
+ private List inputs; // 输入边
+ private List outputs; // 输出边
+ private int parallelism; // 并行度
+ private ResourceProfile resourceProfile; // 资源配置
+}
+```
+
+### 3.4 Job Scheduler模块
+
+#### 3.4.1 设计理念
+
+Job Scheduler负责任务的调度策略,支持多种触发方式:
+- **立即执行**:任务创建后立即执行
+- **定时执行**:按照Cron表达式定时触发
+- **依赖触发**:上游任务完成后触发
+- **事件触发**:外部事件触发
+
+#### 3.4.2 调度策略
+
+```mermaid
+graph TB
+ JS[Job Scheduler]
+
+ JS --> IMM[Immediate Scheduler
立即执行]
+ JS --> CRON[Cron Scheduler
定时调度]
+ JS --> DEP[Dependency Scheduler
依赖调度]
+ JS --> EVT[Event Scheduler
事件调度]
+
+ IMM --> JQ[Job Queue]
+ CRON --> JQ
+ DEP --> JQ
+ EVT --> JQ
+
+ JQ --> JE[Job Executor]
+```
+
+#### 3.4.3 调度器接口
+
+```java
+public interface JobScheduler {
+ // 提交任务
+ ScheduleResult schedule(Job job, SchedulePolicy policy);
+
+ // 取消调度
+ void cancel(String jobId);
+
+ // 暂停调度
+ void pause(String jobId);
+
+ // 恢复调度
+ void resume(String jobId);
+
+ // 获取调度状态
+ ScheduleStatus getStatus(String jobId);
+}
+```
+
+#### 3.4.4 调度策略配置
+
+```java
+// 立即执行
+SchedulePolicy.immediate()
+
+// 每小时执行
+SchedulePolicy.cron("0 0 * * * ?")
+
+// 依赖上游任务
+SchedulePolicy.dependsOn("upstream-job-id")
+
+// 事件触发
+SchedulePolicy.onEvent("data-arrived")
+```
+
+### 3.5 Job Executor模块
+
+#### 3.5.1 设计理念
+
+Job Executor是任务的实际执行引擎,负责将JobGraph转换为可执行的Reactor流,并管理执行过程。
+
+#### 3.5.2 执行流程
+
+```mermaid
+sequenceDiagram
+ participant Scheduler as Job Scheduler
+ participant Executor as Job Executor
+ participant Graph as JobGraph
+ participant Runtime as Reactor Runtime
+ participant Operator as Operators
+
+ Scheduler->>Executor: submit(job)
+ Executor->>Executor: validate(job)
+ Executor->>Graph: getJobGraph()
+ Graph-->>Executor: JobGraph
+
+ Executor->>Executor: buildExecutionPlan()
+
+ loop For Each JobVertex
+ Executor->>Runtime: createFlux(vertex)
+ Runtime->>Operator: instantiate()
+ Operator-->>Runtime: Flux
+ end
+
+ Executor->>Runtime: execute()
+
+ loop Data Processing
+ Runtime->>Operator: process(data)
+ Operator-->>Runtime: result
+ end
+
+ Runtime-->>Executor: completion signal
+ Executor-->>Scheduler: report(status)
+```
+
+#### 3.5.3 执行器接口
+
+```java
+public interface JobExecutor {
+ // 执行任务
+ Mono execute(Job job);
+
+ // 停止任务
+ Mono stop(String jobId);
+
+ // 获取执行状态
+ ExecutionStatus getStatus(String jobId);
+
+ // 获取执行指标
+ ExecutionMetrics getMetrics(String jobId);
+}
+```
+
+#### 3.5.4 执行模式
+
+**单机执行模式**
+```mermaid
+graph LR
+ JE[Job Executor] --> T1[Task 1]
+ JE --> T2[Task 2]
+ JE --> T3[Task 3]
+ T1 --> TP[Thread Pool]
+ T2 --> TP
+ T3 --> TP
+```
+
+**分布式执行模式(未来扩展)**
+```mermaid
+graph TB
+ JM[Job Master] --> W1[Worker 1]
+ JM --> W2[Worker 2]
+ JM --> W3[Worker 3]
+ W1 --> T1[Tasks]
+ W2 --> T2[Tasks]
+ W3 --> T3[Tasks]
+```
+
+### 3.6 Source模块
+
+#### 3.6.1 设计理念
+
+Source是数据的入口,负责从外部系统读取数据并转换为响应式流。所有Source实现都必须支持背压机制。
+
+#### 3.6.2 Source类型
+
+```mermaid
+graph TB
+ Source[Source Interface]
+
+ Source --> BS[Bounded Source
有界数据源]
+ Source --> US[Unbounded Source
无界数据源]
+
+ BS --> FS[File Source]
+ BS --> JS[JDBC Source]
+ BS --> AS[API Source]
+
+ US --> KS[Kafka Source]
+ US --> WS[WebSocket Source]
+ US --> SS[Stream Source]
+```
+
+#### 3.6.3 Source接口定义
+
+```java
+public interface DataSource {
+ // 获取数据流
+ Flux getDataStream();
+
+ // Source类型(有界/无界)
+ SourceType getSourceType();
+
+ // 是否支持并行读取
+ boolean isParallel();
+
+ // 生命周期管理
+ void start();
+ void stop();
+}
+```
+
+### 3.7 Operator模块
+
+#### 3.7.1 设计理念
+
+Operator负责数据转换,分为无状态算子和有状态算子。算子可以链接成算子链,提高执行效率。
+
+#### 3.7.2 Operator分类
+
+```mermaid
+graph TB
+ OP[Operator]
+
+ OP --> SL[Stateless Operators
无状态算子]
+ OP --> SF[Stateful Operators
有状态算子]
+
+ SL --> MAP[Map]
+ SL --> FILTER[Filter]
+ SL --> FLATMAP[FlatMap]
+
+ SF --> AGG[Aggregate]
+ SF --> WIN[Window]
+ SF --> JOIN[Join]
+ SF --> DEDUP[Deduplicate]
+```
+
+#### 3.7.3 Operator接口
+
+```java
+public interface Operator {
+ // 应用转换
+ Flux apply(Flux input);
+
+ // 是否有状态
+ boolean isStateful();
+
+ // 获取算子类型
+ OperatorType getType();
+}
+```
+
+#### 3.7.4 Operator Chain
+
+```mermaid
+graph LR
+ Input[Input Stream] --> OP1[Map Operator]
+ OP1 --> OP2[Filter Operator]
+ OP2 --> OP3[FlatMap Operator]
+ OP3 --> Output[Output Stream]
+
+ subgraph "Operator Chain"
+ OP1
+ OP2
+ OP3
+ end
+```
+
+### 3.8 Sink模块
+
+#### 3.8.1 设计理念
+
+Sink是数据的出口,负责将处理后的数据写入外部系统。支持批量写入以提高效率。
+
+#### 3.8.2 Sink类型
+
+```mermaid
+graph TB
+ Sink[Sink Interface]
+
+ Sink --> DB[Database Sink]
+ Sink --> MQ[Message Queue Sink]
+ Sink --> FILE[File Sink]
+ Sink --> API[API Sink]
+
+ DB --> MYSQL[MySQL Sink]
+ DB --> PG[PostgreSQL Sink]
+ DB --> REDIS[Redis Sink]
+
+ MQ --> KAFKA[Kafka Sink]
+ MQ --> RABBIT[RabbitMQ Sink]
+
+ FILE --> LOCAL[Local File Sink]
+ FILE --> S3[S3 Sink]
+```
+
+#### 3.8.3 Sink接口
+
+```java
+public interface DataSink {
+ // 写入数据
+ Mono write(Flux dataStream);
+
+ // 是否支持批量写入
+ boolean supportsBatch();
+
+ // 是否支持事务
+ boolean supportsTransaction();
+
+ // 生命周期管理
+ void start();
+ void stop();
+}
+```
+
+### 3.9 Connectors模块
+
+#### 3.9.1 设计理念
+
+Connectors提供统一的外部系统连接抽象,采用SPI机制实现插件化扩展。每个Connector可以提供Source和Sink实现。
+
+#### 3.9.2 Connector架构
+
+```mermaid
+graph TB
+ subgraph "Connector Framework"
+ CM[Connector Manager]
+ CR[Connector Registry]
+ CF[Connector Factory]
+ end
+
+ subgraph "Built-in Connectors"
+ JDBC[JDBC Connector]
+ KAFKA[Kafka Connector]
+ HTTP[HTTP Connector]
+ FILE[File Connector]
+ end
+
+ subgraph "Custom Connectors"
+ C1[Custom Connector 1]
+ C2[Custom Connector 2]
+ end
+
+ CM --> CR
+ CM --> CF
+
+ CR --> JDBC
+ CR --> KAFKA
+ CR --> HTTP
+ CR --> FILE
+ CR --> C1
+ CR --> C2
+
+ JDBC --> SRC1[Source]
+ JDBC --> SNK1[Sink]
+ KAFKA --> SRC2[Source]
+ KAFKA --> SNK2[Sink]
+```
+
+#### 3.9.3 Connector接口
+
+```java
+public interface Connector {
+ // Connector标识
+ String getType();
+
+ // 创建Source
+ DataSource createSource(SourceConfig config);
+
+ // 创建Sink
+ DataSink createSink(SinkConfig config);
+
+ // 验证配置
+ void validateConfig(ConnectorConfig config);
+
+ // 获取配置描述
+ ConfigDescriptor getConfigDescriptor();
+}
+```
+
+#### 3.9.4 Connector配置示例
+
+```yaml
+# JDBC Connector配置
+connectors:
+ jdbc:
+ type: jdbc
+ driver: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/db
+ username: user
+ password: password
+ pool:
+ maxSize: 20
+ maxIdleTime: 30m
+
+# Kafka Connector配置
+ kafka:
+ type: kafka
+ bootstrapServers: localhost:9092
+ consumerGroup: etl-consumer
+ topics:
+ - user-events
+ - order-events
+ properties:
+ enable.auto.commit: false
+ max.poll.records: 500
+```
+
+## 4. 模块交互流程
+
+### 4.1 任务提交与执行流程
+
+```mermaid
+sequenceDiagram
+ participant User
+ participant API as Stream API
+ participant SG as StreamGraph
+ participant JG as JobGraph
+ participant Scheduler as Job Scheduler
+ participant Executor as Job Executor
+ participant Runtime as Reactor Runtime
+
+ User->>API: define job
+ API->>SG: build StreamGraph
+ SG->>SG: validate
+ SG->>JG: optimize & transform
+ JG->>JG: operator chain
+ JG->>JG: resource allocation
+
+ User->>Scheduler: submit(job)
+ Scheduler->>Scheduler: schedule policy
+ Scheduler->>Executor: dispatch(job)
+
+ Executor->>JG: getJobGraph()
+ Executor->>Runtime: deploy operators
+ Runtime->>Runtime: connect operators
+ Runtime->>Runtime: start execution
+
+ Runtime-->>Executor: progress updates
+ Executor-->>Scheduler: status updates
+ Scheduler-->>User: job status
+```
+
+### 4.2 StreamGraph到JobGraph转换流程
+
+```mermaid
+flowchart TD
+ Start[User defines ETL job] --> SG[Build StreamGraph]
+ SG --> Validate{Validate DAG}
+ Validate -->|Invalid| Error[Throw Exception]
+ Validate -->|Valid| Optimize[Optimization Phase]
+
+ Optimize --> Chain[Operator Chain Detection]
+ Chain --> Parallel[Parallelism Configuration]
+ Parallel --> Resource[Resource Allocation]
+ Resource --> JG[Generate JobGraph]
+
+ JG --> Schedule[Submit to Scheduler]
+```
+
+### 4.3 任务调度流程
+
+```mermaid
+sequenceDiagram
+ participant User
+ participant Scheduler as Job Scheduler
+ participant Queue as Job Queue
+ participant Executor as Job Executor
+ participant Monitor as Job Monitor
+
+ User->>Scheduler: submit(job, policy)
+
+ alt Immediate
+ Scheduler->>Queue: enqueue(job)
+ else Cron
+ Scheduler->>Scheduler: register cron trigger
+ Note over Scheduler: Wait for trigger time
+ Scheduler->>Queue: enqueue(job)
+ else Dependency
+ Scheduler->>Monitor: watch(upstream job)
+ Monitor-->>Scheduler: upstream completed
+ Scheduler->>Queue: enqueue(job)
+ end
+
+ Queue->>Executor: dispatch(job)
+ Executor->>Executor: execute
+ Executor-->>Monitor: report status
+ Monitor-->>User: notify completion
+```
+
+### 4.4 数据流执行流程
+
+```mermaid
+sequenceDiagram
+ participant Source
+ participant Op1 as Operator 1
+ participant Op2 as Operator 2
+ participant Sink
+ participant State as State Manager
+
+ Source->>Source: read data
+ Source->>Op1: emit(data)
+
+ Op1->>Op1: transform
+ alt Stateful
+ Op1->>State: get state
+ State-->>Op1: state value
+ Op1->>State: update state
+ end
+ Op1->>Op2: emit(result)
+
+ Op2->>Op2: transform
+ Op2->>Sink: emit(result)
+
+ Sink->>Sink: buffer
+ alt Buffer Full
+ Sink->>Sink: flush batch
+ end
+```
+
+### 4.5 检查点协调流程
+
+```mermaid
+sequenceDiagram
+ participant Coordinator as Checkpoint Coordinator
+ participant Source
+ participant Operator
+ participant Sink
+ participant Storage
+
+ Coordinator->>Source: trigger checkpoint(id)
+ Source->>Source: snapshot state
+ Source->>Operator: barrier(id)
+ Source-->>Coordinator: ack(id)
+
+ Operator->>Operator: snapshot state
+ Operator->>Sink: barrier(id)
+ Operator-->>Coordinator: ack(id)
+
+ Sink->>Sink: snapshot state
+ Sink-->>Coordinator: ack(id)
+
+ Coordinator->>Storage: persist checkpoint(id)
+ Storage-->>Coordinator: success
+ Coordinator->>Coordinator: checkpoint completed
+```
+
+## 5. 关键设计决策
+
+### 5.1 为什么需要StreamGraph和JobGraph两层抽象?
+
+**StreamGraph(逻辑图)**
+- 直接映射用户API,保持代码的清晰性
+- 方便调试和问题定位
+- 支持多种优化策略
+
+**JobGraph(物理图)**
+- 优化后的执行计划,提高运行效率
+- 算子链合并,减少序列化开销
+- 资源分配和并行度配置
+
+### 5.2 Job Scheduler的设计考虑
+
+**多种调度策略支持**
+- 满足不同场景需求(实时、定时、依赖)
+- 支持复杂的工作流编排
+
+**任务优先级**
+- 支持任务优先级设置
+- 避免低优先级任务饥饿
+
+**资源感知调度**
+- 根据资源使用情况调度任务
+- 避免资源竞争
+
+### 5.3 响应式设计的优势
+
+**背压机制**
+- 自动调节数据流速
+- 防止内存溢出
+
+**非阻塞IO**
+- 高效利用系统资源
+- 支持高并发
+
+**组合性**
+- 算子可自由组合
+- 代码简洁清晰
+
+### 5.4 Connector插件化设计
+
+**SPI机制**
+- 支持第三方扩展
+- 无需修改核心代码
+
+**统一抽象**
+- 降低学习成本
+- 代码可复用
+
+**配置驱动**
+- 无需编译
+- 灵活配置
+
+## 6. 配置管理
+
+### 6.1 系统配置
+
+```yaml
+# 系统全局配置
+system:
+ name: reactive-etl-framework
+ version: 1.0.0
+
+ # 执行器配置
+ executor:
+ type: single-node # single-node / distributed
+ parallelism: 4 # 默认并行度
+ threadPool:
+ coreSize: 10
+ maxSize: 50
+ queueCapacity: 1000
+
+ # 调度器配置
+ scheduler:
+ type: quartz
+ threadPoolSize: 20
+ jobQueueSize: 1000
+
+ # 检查点配置
+ checkpoint:
+ enabled: true
+ interval: 60s
+ timeout: 10s
+ storage:
+ type: filesystem
+ path: /data/checkpoints
+
+ # 状态后端配置
+ state:
+ backend: memory # memory / rocksdb
+ rocksdb:
+ path: /data/state
+ blockCacheSize: 256m
+
+ # 监控配置
+ metrics:
+ enabled: true
+ reporters:
+ - type: prometheus
+ port: 9090
+ - type: slf4j
+ interval: 60s
+```
+
+### 6.2 任务配置
+
+```yaml
+# ETL任务配置示例
+job:
+ id: user-etl-job
+ name: User Data ETL
+ type: streaming
+
+ # 调度配置
+ schedule:
+ policy: cron
+ expression: "0 0 * * * ?"
+ timezone: Asia/Shanghai
+
+ # 资源配置
+ resources:
+ parallelism: 8
+ memory: 4g
+
+ # Source配置
+ source:
+ connector: kafka
+ type: kafka
+ config:
+ bootstrapServers: localhost:9092
+ topics: [user-events]
+ groupId: etl-consumer
+
+ # Operator配置
+ operators:
+ - name: parse
+ type: map
+ parallelism: 8
+
+ - name: filter
+ type: filter
+ parallelism: 8
+
+ - name: aggregate
+ type: window-aggregate
+ parallelism: 4
+ window:
+ type: tumbling
+ size: 5m
+
+ # Sink配置
+ sink:
+ connector: jdbc
+ type: jdbc
+ config:
+ url: jdbc:mysql://localhost:3306/warehouse
+ table: user_stats
+ batchSize: 100
+ flushInterval: 5s
+```
+
+## 7. 监控与运维
+
+### 7.1 监控指标体系
+
+```mermaid
+graph TB
+ Metrics[Metrics System]
+
+ Metrics --> Job[Job Metrics]
+ Metrics --> Operator[Operator Metrics]
+ Metrics --> Resource[Resource Metrics]
+
+ Job --> JM1[Jobs Running]
+ Job --> JM2[Jobs Success]
+ Job --> JM3[Jobs Failed]
+ Job --> JM4[Job Duration]
+
+ Operator --> OM1[Records In]
+ Operator --> OM2[Records Out]
+ Operator --> OM3[Processing Time]
+ Operator --> OM4[Backpressure]
+
+ Resource --> RM1[CPU Usage]
+ Resource --> RM2[Memory Usage]
+ Resource --> RM3[Thread Pool]
+ Resource --> RM4[Network IO]
+```
+
+### 7.2 关键监控指标
+
+| 指标类别 | 指标名称 | 说明 |
+| --- | --- | --- |
+| 任务指标 | job.running | 运行中的任务数 |
+| 任务指标 | job.completed | 已完成的任务数 |
+| 任务指标 | job.failed | 失败的任务数 |
+| 任务指标 | job.duration | 任务执行时长 |
+| 算子指标 | operator.records.in | 算子输入记录数 |
+| 算子指标 | operator.records.out | 算子输出记录数 |
+| 算子指标 | operator.processing.time | 处理时间 |
+| 算子指标 | operator.backpressure | 背压事件 |
+| 资源指标 | system.cpu.usage | CPU使用率 |
+| 资源指标 | system.memory.usage | 内存使用率 |
+| 资源指标 | threadpool.active | 活跃线程数 |
+| 资源指标 | threadpool.queue.size | 队列大小 |
+
+### 7.3 健康检查机制
+
+```mermaid
+flowchart TD
+ HC[Health Check] --> JS[Job Scheduler Status]
+ HC --> JE[Job Executor Status]
+ HC --> CN[Connectors Status]
+
+ JS --> JS1{Scheduler Running?}
+ JS1 -->|Yes| JS2[Check Job Queue]
+ JS1 -->|No| FAIL1[Health: DOWN]
+ JS2 --> JS3{Queue Size Normal?}
+ JS3 -->|Yes| OK1[Health: UP]
+ JS3 -->|No| WARN1[Health: DEGRADED]
+
+ JE --> JE1{Jobs Running?}
+ JE1 -->|Yes| JE2[Check Backpressure]
+ JE1 -->|No| OK2[Health: UP]
+ JE2 --> JE3{Backpressure High?}
+ JE3 -->|No| OK3[Health: UP]
+ JE3 -->|Yes| WARN2[Health: DEGRADED]
+
+ CN --> CN1{All Connectors Connected?}
+ CN1 -->|Yes| OK4[Health: UP]
+ CN1 -->|No| FAIL2[Health: DOWN]
+```
+
+### 7.4 日志规范
+
+**日志级别使用规范**
+- **TRACE**: 详细的执行追踪信息(生产环境关闭)
+- **DEBUG**: 调试信息,帮助定位问题
+- **INFO**: 关键业务事件(任务启动、完成、检查点等)
+- **WARN**: 警告信息(重试、降级等)
+- **ERROR**: 错误信息(任务失败、异常等)
+
+**结构化日志示例**
+```json
+{
+ "timestamp": "2025-11-09T10:30:00.000Z",
+ "level": "INFO",
+ "logger": "JobExecutor",
+ "jobId": "job-123",
+ "jobName": "user-etl",
+ "event": "JOB_STARTED",
+ "message": "Job started successfully",
+ "metadata": {
+ "parallelism": 8,
+ "operators": 5
+ }
+}
+```
+
+## 8. 扩展性设计
+
+### 8.1 自定义Connector开发
+
+**步骤1:实现Connector接口**
+```java
+public class CustomConnector implements Connector {
+ @Override
+ public String getType() {
+ return "custom";
+ }
+
+ @Override
+ public DataSource createSource(SourceConfig config) {
+ return new CustomSource<>(config);
+ }
+
+ @Override
+ public DataSink createSink(SinkConfig config) {
+ return new CustomSink<>(config);
+ }
+}
+```
+
+**步骤2:实现Source和Sink**
+```java
+public class CustomSource implements DataSource {
+ @Override
+ public Flux getDataStream() {
+ // 实现数据读取逻辑
+ }
+}
+
+public class CustomSink implements DataSink {
+ @Override
+ public Mono write(Flux dataStream) {
+ // 实现数据写入逻辑
+ }
+}
+```
+
+**步骤3:注册Connector**
+在`META-INF/services/com.framework.etl.Connector`文件中添加:
+```
+com.example.CustomConnector
+```
+
+### 8.2 自定义Operator开发
+
+```java
+public class CustomOperator implements Operator {
+
+ @Override
+ public Flux apply(Flux input) {
+ return input
+ .map(this::transform)
+ .filter(this::shouldKeep);
+ }
+
+ @Override
+ public boolean isStateful() {
+ return false;
+ }
+
+ private OUT transform(IN input) {
+ // 转换逻辑
+ }
+
+ private boolean shouldKeep(OUT output) {
+ // 过滤逻辑
+ }
+}
+```
+
+### 8.3 自定义调度策略
+
+```java
+public class CustomSchedulePolicy implements SchedulePolicy {
+
+ @Override
+ public Flux getTriggers() {
+ // 返回触发信号流
+ return Flux.interval(Duration.ofMinutes(30))
+ .map(tick -> new Trigger(triggerTime));
+ }
+
+ @Override
+ public boolean shouldExecute(Job job) {
+ // 判断是否应该执行
+ return checkConditions(job);
+ }
+}
+```
+
+## 9. 使用示例
+
+### 9.1 快速开始:简单ETL任务
+
+```java
+// 创建Job
+Job job = Job.builder()
+ .name("simple-etl")
+ .source(Connectors.kafka()
+ .topic("user-events")
+ .groupId("etl-consumer")
+ .build())
+ .transform(Operators.map(event -> parseUser(event)))
+ .transform(Operators.filter(user -> user.isActive()))
+ .sink(Connectors.jdbc()
+ .table("users")
+ .batchSize(100)
+ .build())
+ .build();
+
+// 提交任务
+jobScheduler.schedule(job, SchedulePolicy.immediate());
+```
+
+### 9.2 定时调度任务
+
+```java
+Job job = Job.builder()
+ .name("daily-report")
+ .source(Connectors.jdbc()
+ .query("SELECT * FROM orders WHERE date = ?")
+ .build())
+ .transform(Operators.aggregate(
+ Orders::getRegion,
+ Orders::getAmount,
+ Double::sum
+ ))
+ .sink(Connectors.file()
+ .path("/reports/daily-{date}.csv")
+ .build())
+ .build();
+
+// 每天凌晨1点执行
+jobScheduler.schedule(job, SchedulePolicy.cron("0 0 1 * * ?"));
+```
+
+### 9.3 复杂的流处理任务
+
+```java
+StreamGraph graph = StreamGraph.builder()
+ // Source
+ .addSource("kafka-source", Connectors.kafka()
+ .topics("events")
+ .build())
+
+ // Parse
+ .addOperator("parse", Operators.map(msg -> parseEvent(msg)))
+
+ // Branch 1: User events
+ .addOperator("filter-user", Operators.filter(e -> e.isUserEvent()))
+ .addOperator("user-aggregate", Operators.windowAggregate(
+ Duration.ofMinutes(5),
+ Events::getUserId,
+ Collectors.counting()
+ ))
+ .addSink("user-sink", Connectors.jdbc().table("user_stats").build())
+
+ // Branch 2: Order events
+ .addOperator("filter-order", Operators.filter(e -> e.isOrderEvent()))
+ .addOperator("order-aggregate", Operators.windowAggregate(
+ Duration.ofMinutes(5),
+ Events::getOrderId,
+ Collectors.summingDouble(Events::getAmount)
+ ))
+ .addSink("order-sink", Connectors.jdbc().table("order_stats").build())
+
+ // Connect edges
+ .connect("kafka-source", "parse")
+ .connect("parse", "filter-user")
+ .connect("parse", "filter-order")
+ .connect("filter-user", "user-aggregate")
+ .connect("user-aggregate", "user-sink")
+ .connect("filter-order", "order-aggregate")
+ .connect("order-aggregate", "order-sink")
+
+ .build();
+
+// 转换为JobGraph并提交
+JobGraph jobGraph = graph.toJobGraph();
+Job job = new Job(jobGraph);
+jobScheduler.schedule(job, SchedulePolicy.immediate());
+```
+
+## 10. 性能优化指南
+
+### 10.1 并行度配置
+
+```mermaid
+graph LR
+ subgraph "Low Parallelism"
+ T1[Task 1] --> R1[Result]
+ end
+
+ subgraph "High Parallelism"
+ T2[Task 1] --> R2[Result]
+ T3[Task 2] --> R2
+ T4[Task 3] --> R2
+ T5[Task 4] --> R2
+ end
+```
+
+**配置建议**
+- CPU密集型:并行度 = CPU核心数
+- IO密集型:并行度 = 2 * CPU核心数
+- 根据数据量动态调整
+
+### 10.2 批处理优化
+
+```yaml
+sink:
+ batchSize: 100 # 批次大小
+ flushInterval: 5s # 刷新间隔
+```
+
+**权衡考虑**
+- 批次越大,吞吐量越高,但延迟增加
+- 批次越小,延迟越低,但吞吐量降低
+
+### 10.3 背压控制策略
+
+| 策略 | 说明 | 适用场景 |
+| --- | --- | --- |
+| BUFFER | 缓冲数据 | 临时性的速度不匹配 |
+| DROP | 丢弃新数据 | 允许丢失部分数据 |
+| LATEST | 保留最新数据 | 只关心最新状态 |
+| ERROR | 抛出异常 | 不允许数据丢失 |
+
+### 10.4 资源配置建议
+
+```yaml
+resources:
+ # JVM配置
+ jvm:
+ heap: 4g
+ metaspace: 512m
+ gc: G1GC
+
+ # 线程池配置
+ threadPool:
+ io:
+ coreSize: 20
+ maxSize: 100
+ compute:
+ coreSize: 8
+ maxSize: 16
+
+ # 缓冲区配置
+ buffer:
+ sourceBuffer: 1000
+ sinkBuffer: 500
+```
+
+## 11. 容错与恢复
+
+### 11.1 故障类型
+
+```mermaid
+graph TB
+ Failures[Failure Types]
+
+ Failures --> TF[Task Failures
任务失败]
+ Failures --> NF[Node Failures
节点故障]
+ Failures --> EF[External Failures
外部系统故障]
+
+ TF --> TF1[Data Error
数据错误]
+ TF --> TF2[Logic Error
逻辑错误]
+
+ NF --> NF1[Process Crash
进程崩溃]
+ NF --> NF2[Network Partition
网络分区]
+
+ EF --> EF1[Source Unavailable
数据源不可用]
+ EF --> EF2[Sink Unavailable
目标系统不可用]
+```
+
+### 11.2 重启策略
+
+```yaml
+restart:
+ # 固定延迟重启
+ strategy: fixed-delay
+ attempts: 3
+ delay: 10s
+
+ # 指数退避重启
+ # strategy: exponential-backoff
+ # initialDelay: 1s
+ # maxDelay: 5m
+ # multiplier: 2
+
+ # 失败率重启
+ # strategy: failure-rate
+ # maxFailuresPerInterval: 3
+ # failureRateInterval: 5m
+ # delay: 10s
+```
+
+### 11.3 检查点恢复流程
+
+```mermaid
+sequenceDiagram
+ participant Job
+ participant Scheduler
+ participant Executor
+ participant Checkpoint
+ participant State
+
+ Note over Job: Job Failed
+
+ Job->>Scheduler: report failure
+ Scheduler->>Scheduler: apply restart strategy
+
+ alt Should Restart
+ Scheduler->>Checkpoint: get latest checkpoint
+ Checkpoint-->>Scheduler: checkpoint-id
+
+ Scheduler->>Executor: restart(job, checkpoint-id)
+ Executor->>Checkpoint: load(checkpoint-id)
+ Checkpoint->>State: restore state
+ State-->>Executor: state restored
+
+ Executor->>Executor: resume from checkpoint
+ Executor-->>Scheduler: job restarted
+ else Max Retries Exceeded
+ Scheduler->>Scheduler: mark job as failed
+ Scheduler-->>Job: job terminated
+ end
+```
+
+## 12. 最佳实践
+
+### 12.1 任务设计原则
+
+1. **单一职责**:每个Job只负责一个业务逻辑
+2. **幂等性**:确保任务可以安全重试
+3. **可观测性**:添加足够的监控指标和日志
+4. **容错性**:合理配置重试和检查点策略
+
+### 12.2 性能优化建议
+
+1. **合理设置并行度**:根据资源和数据量调整
+2. **启用算子链**:减少序列化开销
+3. **批量处理**:使用批量写入提高吞吐量
+4. **状态管理**:大状态使用RocksDB后端
+
+### 12.3 运维建议
+
+1. **监控告警**:设置关键指标告警阈值
+2. **定期备份**:定期备份检查点数据
+3. **资源隔离**:不同优先级任务使用不同资源池
+4. **灰度发布**:新版本先小流量验证
+
+## 13. 未来规划
+
+### 13.1 短期规划(3-6个月)
+
+- 完善Connector生态(MongoDB、ClickHouse、HBase)
+- 实现分布式执行模式
+- 提供Web管理界面
+- 支持SQL API
+
+### 13.2 中期规划(6-12个月)
+
+- 实现Exactly-Once语义
+- 支持动态扩缩容
+- 机器学习特征工程集成
+- 流批一体架构
+
+### 13.3 长期规划(1-2年)
+
+- 云原生支持(Kubernetes Operator)
+- 多租户隔离
+- 实时数据质量监控
+- 智能资源调度
+
+## 14. 参考资料
+
+### 14.1 技术栈
+
+- **响应式编程**: Project Reactor 3.5+
+- **任务调度**: Quartz Scheduler
+- **状态存储**: RocksDB
+- **监控**: Micrometer + Prometheus
+- **序列化**: Protobuf / Avro
+
+### 14.2 设计参考
+
+- Apache Flink架构设计
+- Apache Kafka Streams
+- Spring Cloud Data Flow
+- Reactive Streams规范
+
+### 14.3 相关文档
+
+- [Project Reactor官方文档](https://projectreactor.io/docs)
+- [Reactive Streams规范](https://www.reactive-streams.org/)
+- [Apache Flink文档](https://flink.apache.org/)
+
+## 15. 术语表
+
+| 术语 | 英文 | 说明 |
+| --- | --- | --- |
+| 任务 | Job | 完整的ETL处理流程 |
+| 流图 | StreamGraph | 用户定义的逻辑执行图 |
+| 任务图 | JobGraph | 优化后的物理执行图 |
+| 调度器 | Scheduler | 任务调度组件 |
+| 执行器 | Executor | 任务执行引擎 |
+| 数据源 | Source | 数据输入 |
+| 算子 | Operator | 数据转换 |
+| 输出 | Sink | 数据输出 |
+| 连接器 | Connector | 外部系统连接 |
+| 背压 | Backpressure | 流量控制机制 |
+| 检查点 | Checkpoint | 状态快照 |
+| 算子链 | Operator Chain | 算子优化合并 |
+
+---
+
+**文档版本**: v2.0
+**最后更新**: 2025-11-09
+**维护者**: ETL Framework Team
diff --git a/images/account.png b/images/account.png
new file mode 100644
index 000000000..be0e67a05
Binary files /dev/null and b/images/account.png differ