Apache Griffin 数据质量实战详解
基于已完成部署的 Apache Griffin 服务器开展数据质量实战:REST API 认知、创建 accuracy 度量与 quartz 调度作业、官方示例 predicate 路径不符导致作业卡 NOT_FOUND 的完整排障链、Spark on yarn 端到端执行核验,以及 ES 指标与 metrics API 的结果核验(125000 行、miss 502、准确率 99.5984%)。
Apache Griffin 数据质量实战详解
目标:在已完成部署的 Apache Griffin 服务器上,从零完成一次端到端的数据质量检测实战——通过 REST API 创建 accuracy(准确率)度量与 quartz 调度作业,解决官方示例数据就绪路径与真实数据布局不符导致作业卡 NOT_FOUND 的经典故障,最终在 Elasticsearch 与 metrics API 中核验质量指标。全部请求、响应与日志均来自真实环境实测(准确率指标 99.5984%)。
一、环境信息
1.1 服务器与组件版本
本篇承接本专栏《Apache Griffin Docker Compose 部署指南》完成部署的 Griffin 服务器(batch 形态),将其视为一台"已部署好 Griffin 的数据服务器",所有操作均通过服务端口进行。实测组件版本:
- Griffin Service:0.2.0(
GET /api/v1/version实测返回;部署套件组件标记为 0.3.0) - Hadoop:2.6.5(服务器内安装目录
/apache/hadoop-2.6.5,默认文件系统hdfs://griffin:9000) - Spark:standalone master/worker(
spark://griffin:7077),度量作业经 Livy 以 yarn-cluster 模式提交 - Livy:8998 端口(REST 作业提交通道)
- Elasticsearch:5.5.2(指标存储)
- PostgreSQL:9.3(quartz 调度元数据库);MySQL:5.x(套件内置附加数据库)
- Hive metastore:thrift 9083(被检表元数据)
1.2 服务地址与端口
本篇所有命令均在这台服务器上以可独立执行的 curl 形态给出;从其他机器访问时,把 localhost 替换为该服务器 IP 即可:
| 服务 | 地址 | 用途 |
|---|---|---|
| Griffin Service(REST API + UI) | http://localhost:38080 | 度量/作业/指标管理与查询 |
| Elasticsearch | http://localhost:39200 | 指标检索 |
| Livy | http://localhost:38998 | Spark 批作业状态查询 |
| YARN ResourceManager | http://localhost:38088 | Spark on yarn 资源与作业页面 |
| Hive metastore | localhost:39083 | 被检表元数据(thrift) |
环境就绪的实测核验:
curl http://localhost:38080/api/v1/version
0.2.0
1.3 demo 数据分布
部署套件启动时自动生成了两组 demo Hive 表(经元数据 API 实测确认存在):
curl "http://localhost:38080/api/v1/metadata/hive/tables/names?db=default"
["demo_src","demo_tgt"]
数据的真实 HDFS 布局(本篇排障的关键事实,实测探明):表目录位于 /griffin/data/batch/demo_src 与 /griffin/data/batch/demo_tgt,按天 + 小时两级分区(实测含 dt=20261014/hour=14、hour=15、hour=16),每个 hour 分区下有数据文件与 _DONE 就绪标志文件,单文件约 1.36MB、共 125000 行,其中预置约 0.4% 缺失(502 行)。
二、Service REST API 认知
2.1 核心 API 总览
动手前先认知 Griffin Service 的 REST 面。实测可用的核心 API 如下:
| API | 方法 | 用途 | 本篇使用 |
|---|---|---|---|
/api/v1/version | GET | 服务版本 | 环境核验 |
/api/v1/measures | GET/POST/PUT | 度量定义的查询/创建/更新 | 三、六 |
/api/v1/measures/{id} | GET | 单个度量详情 | 三 |
/api/v1/jobs | GET/POST | 作业查询/创建 | 四、六 |
/api/v1/jobs/{id} | DELETE | 删除作业 | 六 |
/api/v1/jobs/instances?jobId=... | GET | 作业执行实例列表 | 四、六 |
/api/v1/jobs/health | GET | 作业健康统计 | 五、七 |
/api/v1/metrics | GET | 指标聚合查询 | 七 |
/api/v1/metadata/hive/dbs、/api/v1/metadata/hive/tables/names | GET | Hive 库表元数据 | 一、五 |
其余服务面(Livy、ES、YARN)的实测核验:
curl http://localhost:38998/batches
{"from":0,"total":0,"sessions":[]}
curl http://localhost:39200/_cluster/health?pretty
{"cluster_name":"elasticsearch","status":"green","number_of_nodes":1,...}
(输出节选,HTTP 200;初始无任何 Spark 作业与指标索引,是干净的起点。)
⚠️ 注意:API 能力与版本强相关。实测 0.2.0 服务上,
POST /api/v1/jobs/trigger/10(按 id 手动触发,0.6.0 官方接口文档与 postman 集合中存在)返回 404——该版本没有此端点,作业触发只能依赖 cron 周期调度。动手前务必先用GET /api/v1/version确认版本,再决定可用 API。
2.2 度量数据源与元数据接入
度量定义通过 HIVE 类型连接器读取 Hive 表,其 where 条件按分区模板过滤(如 dt=#YYYYMMdd# AND hour=#HH#),分区占位符在执行时由数据时间戳代入。库表可查性实测:
curl http://localhost:38080/api/v1/metadata/hive/dbs
["default"]
default 库与 1.3 节的 demo_src、demo_tgt 两表即为本次实战的被检对象:demo_src 为源表、demo_tgt 为目标表,准确率规则将逐行比对两表。
三、创建 accuracy 度量(Measure)
3.1 技术拓展:DQ 度量类型
💡 技术拓展:Griffin 的度量类型(
dq.type)不止准确率一种,常见取值横向对比——
类型 dq.type 度量内容 典型输出 准确率 ACCURACY 源表与目标表按规则比对的差异行 total/miss/matched 完整性 COMPLETENESS 字段空值与缺失比例 按列缺失统计 数据画像 PROFILING 各列分布统计(最大/最小/均值/去重数) 列级统计值 时效性 TIMELINESS 数据到达延迟(流场景) 延迟分布 本文实测采用 ACCURACY:它是官方示例的默认类型、指标语义最直观,且在本环境的端到端链路中完整跑通,适合作为部署后的第一个质量度量。
3.2 请求体与创建
度量定义是一个 JSON 对象,包含:两路数据源(source/target,各挂一个 HIVE 连接器)、逐行比对规则、以及数据就绪谓词。将以下官方示例请求体保存为 /root/measure-accuracy.json(原文照抄,其中 root.path 为官方 postman 集合原值,第五章将排障该路径):
{
"name":"accuracy_measure",
"measure.type":"griffin",
"dq.type":"ACCURACY",
"process.type":"BATCH",
"owner":"test",
"description":"measure created via REST API experiment",
"data.sources":[
{
"name":"source",
"connectors":[
{
"name":"connector_name_source",
"type":"HIVE",
"version":"1.2",
"data.unit":"1hour",
"data.time.zone":"UTC(WET,GMT)",
"config":{
"database":"default",
"table.name":"demo_src",
"where":"dt=#YYYYMMdd# AND hour=#HH#"
},
"predicates":[
{
"type":"file.exist",
"config":{
"root.path":"hdfs:///griffin/demo_src",
"path":"/dt=#YYYYMMdd#/hour=#HH#/_DONE"
}
}
]
}
]
},
{
"name":"target",
"connectors":[
{
"name":"connector_name_target",
"type":"HIVE",
"version":"1.2",
"data.time.zone":"UTC(WET,GMT)",
"data.unit":"1hour",
"config":{
"database":"default",
"table.name":"demo_tgt",
"where":"dt=#YYYYMMdd# AND hour=#HH#"
},
"predicates":[
{
"type":"file.exist",
"config":{
"root.path":"hdfs:///griffin/demo_src",
"path":"/dt=#YYYYMMdd#/hour=#HH#/_DONE"
}
}
]
}
]
}
],
"evaluate.rule":{
"rules":[
{
"dsl.type":"griffin-dsl",
"dq.type":"ACCURACY",
"name":"accuracy",
"rule":"source.desc=target.desc"
}
]
}
}
创建度量(POST,返回 201 即成功):
curl -s -w "\nHTTP_CODE=%{http_code}\n" -X POST http://localhost:38080/api/v1/measures \
-H "Content-Type: application/json" \
-d @/root/measure-accuracy.json
响应(输出节选,实测):
{"measure.type":"griffin","id":1,"name":"accuracy_measure","owner":"test",...,
"sinks":["ELASTICSEARCH","HDFS"],
"evaluate.rule":{"id":2,"rules":[{"id":3,"rule":"source.desc=target.desc","dsl.type":"griffin-dsl","dq.type":"ACCURACY"}]}}
HTTP_CODE=201
逐项解读:id=1 是服务端分配的度量 ID(后续作业按它引用);sinks 显示服务端自动挂载了 ELASTICSEARCH 与 HDFS 两个指标存储(指标将同时写入 ES 索引与 HDFS 备份);evaluate.rule 中的比对规则 source.desc=target.desc 表示逐行比较两表的 desc 字段。
3.3 创建结果核验
curl -s -o /dev/null -w "%{http_code}" http://localhost:38080/api/v1/measures/1
200
(HTTP 200,返回完整度量 JSON,含 id=1、name=accuracy_measure 与两个 sink 配置。)度量定义此时只是"静态规则",尚不会有任何计算发生——它需要被下一章的作业调度起来。
四、创建调度作业(Job)
4.1 quartz 调度与 predicate 机制
作业(Job)把度量变成"按周期执行的调度任务",两个机制必须理解:
- quartz 调度:作业创建后在服务端注册 quartz 任务(实测返回
quartz.group=BA),按cron.expression与cron.time.zone周期触发,调度元数据落在 PostgreSQL 的 quartz 库; - 数据就绪检查(predicate):每轮触发先执行
file.exist谓词——按分区模板拼出_DONE标志文件路径(如/dt=#YYYYMMdd#/hour=#HH#/_DONE)探测 HDFS,检查节奏由predicate.config控制(实测示例:每 1 分钟查一次、最多重复 2 次);未就绪则本轮执行实例标记为NOT_FOUND等待下一轮,不会空跑 Spark 作业。
4.2 请求体与创建
将以下作业请求体保存为 /root/accuracy-job.json(在官方 postman 结构上落本环境实测值:引用度量 measure.id=1,作业名 accuracy_job_exp,每 4 分钟调度一次,数据分段取前 1 小时):
{
"measure.id": 1,
"job.name": "accuracy_job_exp",
"job.type": "batch",
"cron.expression": "0 0/4 * * * ?",
"cron.time.zone": "GMT+8:00",
"predicate.config": {
"checkdonefile.schedule": {
"interval": "1m",
"repeat": 2
}
},
"data.segments": [
{
"data.connector.name": "connector_name_source",
"as.baseline": true,
"segment.range": {
"begin": "-1h",
"length": "1h"
}
},
{
"data.connector.name": "connector_name_target",
"segment.range": {
"begin": "-1h",
"length": "1h"
}
}
]
}
创建作业:
curl -s -w "\nHTTP_CODE=%{http_code}\n" -X POST http://localhost:38080/api/v1/jobs \
-H "Content-Type: application/json" \
-d @/root/accuracy-job.json
响应(输出节选,实测):
{"id":10,"quartz.name":"accuracy_job_exp_1791990423152","quartz.group":"BA",...}
HTTP_CODE=201
id=10 为作业 ID,quartz.name 带毫秒后缀是 quartz 注册名。
4.3 执行实例观察(故障出现)
作业到点自动触发。查询执行实例:
curl "http://localhost:38080/api/v1/jobs/instances?jobId=10&page=0&size=10"
实测状态变化(输出节选):实例 {"id":15,"state":"FINDING",...} 创建后进入 FINDING(寻找数据阶段);约 2 分钟后再次查询变为 {"state":"NOT_FOUND"}。同时 Livy 侧始终没有提交任何 Spark 作业:
curl http://localhost:38998/batches
{"from":0,"total":0,"sessions":[]}
作业健康统计也显示作业不健康:
curl http://localhost:38080/api/v1/jobs/health
{"healthyJobCount":0,"jobCount":1}
(HTTP 200。)现象明确:作业能创建、能到点触发,但每轮都卡在"数据就绪检查"上,Spark 从未执行。下一章完整排障。
五、排障:predicate 路径不符导致作业卡 NOT_FOUND
5.1 故障现象与日志特征
作业实例状态 FINDING → NOT_FOUND 循环、Livy 无作业提交。查看服务日志(/root/service/service.log),每一轮调度都有相同特征行(实测原文):
2026-10-14 15:10:00.116 INFO [ryBean_Worker-4] o.a.g.c.j.FileExistPredicator : Predicate path: hdfs:///griffin/demo_src/dt=20261014/hour=14/_DONE
2026-10-14 15:10:00.122 INFO [ryBean_Worker-4] o.a.g.c.j.FileExistPredicator : Predicate path: hdfs:///griffin/demo_src/dt=20261014/hour=14/_DONE doesn't exist.
日志特征即 Predicate path: ... doesn't exist.——就绪谓词在 HDFS 上找不到 _DONE 文件。
5.2 定位过程(两步假设验证)
假设一:路径缺 authority(hdfs:///)导致解析失败。 把度量的 root.path 改为带 authority 的 hdfs://griffin:9000/griffin/demo_src 后 PUT 更新度量(HTTP 200),删除旧作业重建(新作业 id=25),predicate 仍然报 doesn't exist(service.log 15:16:00.071)。假设一被证伪——同时也说明无 authority 的 URI 在 0.2.0 上可被默认文件系统补全,不是根因。
假设二(决定性实验):_DONE 文件真的不存在吗?文件到底在哪? 在 Griffin 服务器上,用其内置 Hadoop 2.6.5(/apache/hadoop-2.6.5)的 classpath 运行独立 Java 探测程序,直接调用 Hadoop FileSystem.isFile(...) 对比两组路径,实测输出:
fs class: org.apache.hadoop.hdfs.DistributedFileSystem
fs uri: hdfs://griffin:9000
isFile(hdfs://griffin:9000/griffin/demo_src/dt=20261014/hour=14/_DONE): false
isFile(hdfs://griffin:9000/griffin/data/batch/demo_src/dt=20261014/hour=14/_DONE): true
isFile(hdfs://griffin:9000/griffin/data/batch/demo_tgt/dt=20261014/hour=14/_DONE): true
结论一目了然:/griffin/demo_src 下确实没有 _DONE;真实文件在 /griffin/data/batch/demo_src(与 demo_tgt)之下。再用元数据接口核对 demo_src 表的存储位置(location),实测为 hdfs://griffin:9000/griffin/data/batch/demo_src——Hive 表 location 才是数据的真实家。
5.3 根因结论
根因:官方 postman 示例的 predicate root.path 写的是 hdfs:///griffin/demo_src,比真实数据布局少了 data/batch 段(真实位置 /griffin/data/batch/demo_src),与套件内置 demo 数据的 HDFS 布局不符,导致 FileExistPredicator 永远返回 false,作业永远 NOT_FOUND。 补充两点实测佐证:其一,服务日志中有 Setting fs.defaultFS:hdfs://griffin:9000,谓词使用的文件系统单例由该默认值初始化,所以无 authority 的 hdfs:/// 前缀本身可正常补全;其二,对服务 jar 反编译(javap)确认 FSUtil.isFileExist 的真实逻辑是 fileSystem.isFile(path) || fileSystem.isDirectory(path),路径正确时文件与目录任一存在即通过。
⚠️ 注意:这是"能部署、跑不出指标"的最典型故障。排查口诀:先看
service.log的Predicate path: ... doesn't exist.行拿到被探测的完整路径,再对比 Hive 表 location(元数据接口)确认真实数据目录,两者差在哪一段,root.path就补哪一段。
六、修复度量并端到端跑通
6.1 修正 predicate 路径
按根因修正度量定义:source 连接器的 root.path 改为 hdfs://griffin:9000/griffin/data/batch/demo_src,target 改为 hdfs://griffin:9000/griffin/data/batch/demo_tgt,其余不变。将修正后的完整请求体保存为 /root/measure-accuracy-fix2.json(与 3.2 节请求体的区别仅在两处 root.path,以及末尾新增的 "id": 1 表示更新对象):
{
"name": "accuracy_measure",
"measure.type": "griffin",
"dq.type": "ACCURACY",
"process.type": "BATCH",
"owner": "test",
"description": "measure created via REST API experiment",
"data.sources": [
{
"name": "source",
"connectors": [
{
"name": "connector_name_source",
"type": "HIVE",
"version": "1.2",
"data.unit": "1hour",
"data.time.zone": "UTC(WET,GMT)",
"config": {
"database": "default",
"table.name": "demo_src",
"where": "dt=#YYYYMMdd# AND hour=#HH#"
},
"predicates": [
{
"type": "file.exist",
"config": {
"root.path": "hdfs://griffin:9000/griffin/data/batch/demo_src",
"path": "/dt=#YYYYMMdd#/hour=#HH#/_DONE"
}
}
]
}
]
},
{
"name": "target",
"connectors": [
{
"name": "connector_name_target",
"type": "HIVE",
"version": "1.2",
"data.unit": "1hour",
"data.time.zone": "UTC(WET,GMT)",
"config": {
"database": "default",
"table.name": "demo_tgt",
"where": "dt=#YYYYMMdd# AND hour=#HH#"
},
"predicates": [
{
"type": "file.exist",
"config": {
"root.path": "hdfs://griffin:9000/griffin/data/batch/demo_tgt",
"path": "/dt=#YYYYMMdd#/hour=#HH#/_DONE"
}
}
]
}
]
}
],
"evaluate.rule": {
"rules": [
{
"dsl.type": "griffin-dsl",
"dq.type": "ACCURACY",
"name": "accuracy",
"rule": "source.desc=target.desc"
}
]
},
"id": 1
}
PUT 更新度量:
curl -s -o /dev/null -w "%{http_code}" -X PUT http://localhost:38080/api/v1/measures \
-H "Content-Type: application/json" \
-d @/root/measure-accuracy-fix2.json
200
(HTTP 200。注意:PUT 更新后度量内的 connector/predicate 子对象 ID 会被服务端重建——实测连接器 ID 由 5/8 变为 35/38,属正常行为,引用度量时始终用顶层 measure.id=1。)
6.2 重建作业
先删除旧作业(含假设一阶段重建的 id=25):
curl -s -o /dev/null -w "%{http_code}" -X DELETE http://localhost:38080/api/v1/jobs/25
204
再以更密的调度周期(每 2 分钟)创建新作业,作业名 accuracy_job_exp3(请求体结构同 4.2 节,job.name 改为 accuracy_job_exp3、cron.expression 改为 0 0/2 * * * ?,保存为 /root/accuracy-job-fix.json 后执行):
curl -s -w "\nHTTP_CODE=%{http_code}\n" -X POST http://localhost:38080/api/v1/jobs \
-H "Content-Type: application/json" \
-d @/root/accuracy-job-fix.json
响应(输出节选,实测):
{"id":40,"quartz.name":"accuracy_job_exp3_1791990423152","quartz.group":"BA",...}
HTTP_CODE=201
6.3 predicate 通过与 Spark 执行核验
下一轮调度到达时,服务日志(/root/service/service.log)出现就绪检查通过的关键行(实测原文,... 为实测日志原样):
2026-10-14 15:20:15.765 INFO [ryBean_Worker-3] FileExistPredicator : Predicate path: hdfs://griffin:9000/griffin/data/batch/demo_src/dt=20261014/hour=14/_DONE
2026-10-14 15:20:15.793 INFO [ryBean_Worker-3] FileExistPredicator : Predicate path: .../_DONE exists.
2026-10-14 15:20:15.796 INFO [ryBean_Worker-3] FileExistPredicator : ... demo_tgt .../_DONE exists.
源表与目标表的 _DONE 均确认存在,Spark 作业随即经 Livy 提交上 yarn。等待约 1 分钟后查询 Livy 批作业:
curl http://localhost:38998/batches
{"id":0,"state":"success","appId":"application_1791990164994_0001","sparkUiUrl":"http://griffin:8088/proxy/application_1791990164994_0001/"}
(HTTP 200。state=success 表示 Spark 计算完成;sparkUiUrl 为服务器内部主机名视角的 yarn proxy 地址,宿主机可通过 38088 端口的 YARN 页面查看同一作业。)
再查作业执行实例:
curl "http://localhost:38080/api/v1/jobs/instances?jobId=40&page=0&size=10"
实例状态(输出节选,实测):
{"id":45,"sessionId":0,"state":"SUCCESS","appId":"application_1791990164994_0001",...}
state=SUCCESS 与 Livy 的 success、yarn 的 application_1791990164994_0001 三者对应,端到端链路(调度 → 就绪检查 → Spark on yarn 计算 → 指标写出)至此全部跑通。
七、结果核验:ES 指标与 metrics API
7.1 ES 指标索引
指标由度量定义中自动挂载的 ELASTICSEARCH sink 写入。实测索引列表:
curl http://localhost:39200/_cat/indices?v
health status index uuid pri rep docs.count docs.deleted store.size
yellow open griffin szaYHsDkTTGM6pXp2CiMIg 5 1 1 0 5.2kb
单节点环境下 1 副本无法分配,索引健康 yellow 属预期。检索准确率指标:
curl "http://localhost:39200/griffin/accuracy/_search?pretty&filter_path=hits.hits._source" \
-d '{"query":{"match_all":{}},"sort":[{"tmst":{"order":"asc"}}],"size":3}'
{"hits":{"hits":[{"_source":{"name":"accuracy_job_exp3","tmst":1791987600000,
"value":{"total":125000,"miss":502,"matched":124498}}}]}}
指标解读:total=125000 为比对总行数,miss=502 为不一致行数,matched=124498 为一致行数,准确率 = 124498/125000 ≈ 99.5984%——与 demo 数据预置的约 0.4% 缺失(502 行)完全吻合,说明指标计算正确。
7.2 metrics API 聚合查询
同样的指标经 Service API 按度量名聚合返回:
curl http://localhost:38080/api/v1/metrics
{"accuracy_measure":[{"name":"accuracy_job_exp3","type":"ACCURACY","owner":"test",
"metricValues":[{"name":"accuracy_job_exp3","tmst":1791987600000,
"value":{"total":125000,"miss":502,"matched":124498}}]}]} HTTP 200
(HTTP 200,输出按"度量名 → 指标序列"组织,metricValues 数组随每轮执行追加,适合画趋势图。)
7.3 作业健康与后续调度
curl http://localhost:38080/api/v1/jobs/health
{"healthyJobCount":1,"jobCount":1}
(修复后 healthyJobCount 由 0 变 1。)作业 id=40 处于活跃调度状态:每 2 分钟到点后重复"就绪检查 → Spark on yarn 计算 → 指标追加写入 ES/HDFS",每次执行都会在 griffin/accuracy 索引与 /api/v1/metrics 的 metricValues 中追加一条新时间戳记录。验证方法:隔 2 分钟以上重查 7.1 节的 _search,hits.total 与 tmst 数量应增长;不再需要时按第八章方法删除作业即可停止调度。
八、常见问题(FAQ)
Q1:作业一直 NOT_FOUND,Livy 里也没有作业?
就是本篇第五章的完整链路。排查三步:一看 /root/service/service.log 的 Predicate path: ... doesn't exist. 行,拿到被探测的完整路径;二用元数据接口核对 Hive 表 location,确认真实数据目录;三把度量中 predicates 的 root.path 改成真实目录后 PUT 更新度量、重建作业。切勿只改 URI 写法(hdfs:/// 与 hdfs://host:9000 实测等价,0.2.0 上均可用),路径段缺失才是根因。
Q2:POST /api/v1/jobs/trigger/:id 返回 404?
实测 0.2.0 服务没有该端点(0.6.0 官方接口文档与 postman 集合里有)。解决:不依赖手动触发,等 cron 周期到点自动调度即可;如需手动验证,可把 cron.expression 临时调成 0 0/2 * * * ?(每 2 分钟)缩短等待,验证完再改回。
Q3:为什么分区小时与我的本地时间对不上?
本环境的时区分工实测为:作业调度时区 cron.time.zone=GMT+8:00,连接器数据时区 data.time.zone=UTC(WET,GMT),而 demo 数据的分区目录由服务器时钟(UTC)生成(实测 dt=20261014/hour=14/15/16)。定位分区时以 UTC 分区为准;若自建度量,建议把连接器时区与数据生成分区所用的时区统一,避免 #HH# 代入后找错分区。
Q4:ES 索引健康是 yellow,有影响吗? 无影响。默认指标索引 5 主分片 1 副本,单节点环境副本分片无法分配,yellow 属预期;检索与写入均正常(见 7.1 节实测)。多节点部署或调整副本数后即转 green。
Q5:PUT 更新度量后,里面的 id 变了?
正常行为。实测 PUT 后度量内 connector/predicate 子对象 ID 由 5/8 重建为 35/38,顶层 measure.id 不变。引用关系(measure.id)一律用顶层 ID,不要缓存子对象 ID。
Q6:指标会一直追加吗?磁盘怎么控制?
会。活跃作业每轮调度都追加一条指标(ES 索引 + HDFS 备份双写)。不需要时删除作业停止调度:DELETE /api/v1/jobs/{id} 返回 204 即停;ES 侧历史指标可按 tmst 时间戳清理或按留存策略滚动索引。
九、参考链接
- Apache Griffin 官网:https://griffin.apache.org/
- 官方代码仓库:https://github.com/apache/griffin
- 官方 REST 接口 postman 集合(0.6.0 tag 内
griffin-doc/service/postman/griffin.json,本篇度量/作业请求体来源):https://github.com/apache/griffin/tree/griffin-0.6.0/griffin-doc/service/postman - 官方部署指南:位于 0.6.0 tag 的
griffin-doc目录下(官方指南文件与 demo 数据说明,获取方式见《Apache Griffin Docker Compose 部署指南》) - 本专栏配套文档:《Apache Griffin 介绍与核心概念详解》《Apache Griffin Docker Compose 部署指南》