[监控表] — Java代码验证表关系代码可拷贝运行
# 一、写这段代码的目的
前文我们通过 SQL + GET_BYTE 验证过业务表和基础表之间的关系,但 Phoenix 对 BINARY
类型的支持有限,查询写法冗长且性能一般。
在实际开发和调试中,我们更希望能用 Java 程序直接解析 UUID,做到:
- 拆解出 前 16B = metric UUID,并关联到
METRICS_METADATA_UUID
表获取指标名; - 拆解出 后 4B = hostId,从而知道这条指标数据来自哪台主机;
- 顺便统计每个 UUID 出现的次数(count),方便分析数据分布。
# 二、Java 验证程序
下面是一段完整的 Java 程序(含工具方法),直接运行即可打印出指标、metaUuid、hostId 的对应关系:
package org.example;
import java.sql.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class DebugPhoenixSQL {
public static void main(String[] args) throws Exception {
try (Connection conn = DriverManager.getConnection("jdbc:phoenix:dev1:2181:/ams-hbase-unsecure")) {
// ✅ SQL: 按 UUID 聚合,拿到 record 表里的所有 UUID 和 count
String sql = "SELECT UUID, COUNT(1) AS CNT FROM METRIC_RECORD_UUID GROUP BY UUID LIMIT 10000";
analyzeWithMetadata(conn, sql);
}
}
/**
* 解析 record 表的 UUID,并关联到 metadata 表
*/
private static void analyzeWithMetadata(Connection conn, String sql) throws SQLException {
System.out.println(">>> 执行SQL: " + sql);
// 缓存:metaUuidHex -> metricName
Map<String, String> metaCache = new HashMap<>();
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
byte[] uuid = rs.getBytes("UUID");
long count = rs.getLong("CNT");
if (uuid == null || uuid.length != 20) continue;
// 前16B = metric UUID
byte[] metaPart = Arrays.copyOfRange(uuid, 0, 16);
String metaHex = bytesToHex(metaPart);
// 后4B = hostId
byte[] hostPart = Arrays.copyOfRange(uuid, 16, 20);
String hostHex = bytesToHex(hostPart);
// 查询缓存 / 元数据表
String metricName = metaCache.get(metaHex);
if (metricName == null) {
metricName = fetchMetricName(conn, metaPart);
metaCache.put(metaHex, metricName);
}
System.out.printf("metric=%s, metaUuid=%s, hostId=%s, count=%d%n",
metricName, metaHex, hostHex, count);
}
}
}
/**
* 去 metadata 表查询 UUID 对应的 metric_name
*/
private static String fetchMetricName(Connection conn, byte[] metaUuid) throws SQLException {
try (PreparedStatement ps = conn.prepareStatement(
"SELECT METRIC_NAME, APP_ID FROM METRICS_METADATA_UUID WHERE UUID=?")) {
ps.setBytes(1, metaUuid);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return rs.getString("METRIC_NAME") + " (app=" + rs.getString("APP_ID") + ")";
}
}
return "未知指标";
}
/**
* 工具方法:byte[] -> hex
*/
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) sb.append(String.format("%02X", b));
return sb.toString();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# 三、Maven 依赖配置
要让这段代码运行,需要引入 Phoenix 和 Hadoop 的依赖。
以下是一个最小可运行的 pom.xml
配置:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>phoenix-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Phoenix thick driver + HBase 2.4.x -->
<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-core</artifactId>
<version>5.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-hbase-compat-2.4.1</artifactId>
<version>5.1.2</version>
</dependency>
<!-- Hadoop client for config -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>3.3.4</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.36</version>
</dependency>
</dependencies>
</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 四、运行效果
执行后会打印出类似结果:
metric=dfs.FsVolume.TotalDataFileIos (app=datanode), metaUuid=8CA477CC4A3D7D4F42479F7FE2968784, hostId=9CDC8F97, count=1201
metric=dfs.FsVolume.TotalDataFileIos (app=datanode), metaUuid=8CA477CC4A3D7D4F42479F7FE2968784, hostId=6ED2F093, count=1203
metric=dfs.FsVolume.TotalDataFileIos (app=datanode), metaUuid=8CA477CC4A3D7D4F42479F7FE2968784, hostId=2D31224D, count=1211
1
2
3
2
3
从结果可以清楚看到:
- 同一个 metaUuid(指标)在不同的 hostId(主机)上都有上报;
- 这正好印证了 UUID 拼接的逻辑:16b 指标 + 4b 主机 = 20b 唯一记录。
- 01
- [/metrics/metadata] — 元数据查询和使用 GET09-12
- 02
- [/metrics/metadata] — 请求完整链路解读09-12
- 03
- [/metrics/metadata] — 缓存数据装载 Phoenix09-12