Java

GreptimeDB 使用不同的客户端库来写入和查询数据。 你根据需求可以选择合适的客户端库。

写入数据

GreptimeDB 提供了一个 ingester 库来帮助你写入数据。 它使用 gRPC 协议,支持自动生成表结构,无需在写入数据前创建表。 更多信息请参考 自动生成表结构。

GreptimeDB 提供的 Java ingester SDK 是一个轻量级库,具有以下特点:

  • 基于 SPI 的可扩展网络传输层,提供了使用 gRPC 框架的默认实现。
  • 非阻塞、纯异步的易于使用的 API。
  • 默认情况下自动收集各种性能指标,然后可以配置并将其写入本地文件。
  • 能够对关键对象进行内存快照,配置并将其写入本地文件。这对于解决复杂问题很有帮助。

安装

  1. 安装 Java 开发工具包(JDK)

确保你的系统已安装 JDK 8 或更高版本。有关如何检查 Java 版本并安装 JDK 的更多信息,请参见 Oracle JDK 安装概述文档

  1. 将 GreptimeDB Java SDK 添加为依赖项

如果你使用的是 Maven,请将以下内容添加到 pom.xml 的依赖项列表中:

xml

1. <dependency>
2. <groupId>io.greptime</groupId>
3. <artifactId>ingester-all</artifactId>
4. <version>${latest_version}</version>
5. </dependency>

最新版本可以在 这里 查看。

配置依赖项后,请确保它们对项目可用,这可能需要在 IDE 中刷新项目或运行依赖项管理器。

连接数据库

连接 GreptimeDB 时,通常需要用户名和密码。 关于如何设置 GreptimeDB 的鉴权方式,请参考鉴权。 这里我们在使用 ingester 库连接 GreptimeDB 时设置用户名和密码。

下方的代码展示了以最简单的配置连接到 GreptimeDB 的方法。 如果想要自定义连接选项,请参考 API 文档。 请注意每个选项的注释,它们提供了对其各自角色的详细解释。

java

1. // GreptimeDB has a default database named "public" in the default catalog "greptime",
2. // we can use it as the test database
3. String database = "public";
4. // By default, GreptimeDB listens on port 4001 using the gRPC protocol.
5. // We can provide multiple endpoints that point to the same GreptimeDB cluster.
6. // The client will make calls to these endpoints based on a load balancing strategy.
7. String[] endpoints = {"127.0.0.1:4001"};
8. // Sets authentication information.
9. AuthInfo authInfo = new AuthInfo("username", "password");
10. GreptimeOptions opts = GreptimeOptions.newBuilder(endpoints, database)
11. // If the database does not require authentication, we can use AuthInfo.noAuthorization() as the parameter.
12. .authInfo(authInfo)
13. // A good start ^_^
14. .build();

16. GreptimeDB client = GreptimeDB.create(opts);

行对象

表中的每条行数据包含三种类型的列:Tag、Timestamp 和 Field。更多信息请参考 数据模型。 列值的类型可以是 String、Float、Int、Timestamp 等。更多信息请参考 数据类型。

Java ingester SDK 使用 Table 来表示表中的多行数据。我们可以将行数据项添加到 Table 对象中,然后写入 GreptimeDB。

我们还可以基本的 POJO 对象作为另一种替代方法进行写入。这种方法需要使用 Greptime 的注解,但它们很容易使用。

创建行数据

下面的例子展示了如何创建包含 Tag、Timestamp 和 Field 列的行。Tag 列是 String 类型,Timestamp 列是 Timestamp 类型,Field 列是 Float 类型。

java

1. // Creates schemas
2. TableSchema cpuMetricSchema = TableSchema.newBuilder("cpu_metric") //
3. .addColumn("host", SemanticType.Tag, DataType.String) //
4. .addColumn("ts", SemanticType.Timestamp, DataType.TimestampMillisecond) //
5. .addColumn("cpu_user", SemanticType.Field, DataType.Float64) //
6. .addColumn("cpu_sys", SemanticType.Field, DataType.Float64) //
7. .build();
8. Table cpuMetric = Table.from(cpuMetricSchema);

10. String host = "127.0.0.1";
11. long ts = System.currentTimeMillis();
12. double cpuUser = 0.1;
13. double cpuSys = 0.12;
14. cpuMetric.addRow(host, ts, cpuUser, cpuSys);

为了提高写入数据的效率,你可以一次创建多行数据写入 GreptimeDB。

java

1. // Creates schemas
2. TableSchema cpuMetricSchema = TableSchema.newBuilder("cpu_metric") //
3. .addColumn("host", SemanticType.Tag, DataType.String) //
4. .addColumn("ts", SemanticType.Timestamp, DataType.TimestampMillisecond) //
5. .addColumn("cpu_user", SemanticType.Field, DataType.Float64) //
6. .addColumn("cpu_sys", SemanticType.Field, DataType.Float64) //
7. .build();

9. TableSchema memMetricSchema = TableSchema.newBuilder("mem_metric") //
10. .addColumn("host", SemanticType.Tag, DataType.String) //
11. .addColumn("ts", SemanticType.Timestamp, DataType.TimestampMillisecond) //
12. .addColumn("mem_usage", SemanticType.Field, DataType.Float64) //
13. .build();

15. Table cpuMetric = Table.from(cpuMetricSchema);
16. Table memMetric = Table.from(memMetricSchema);

18. // Adds row data items
19. for (int i = 0; i < 10; i++) {
20. String host = "127.0.0." + i;
21. long ts = System.currentTimeMillis();
22. double cpuUser = i + 0.1;
23. double cpuSys = i + 0.12;
24. cpuMetric.addRow(host, ts, cpuUser, cpuSys);
25. }

27. for (int i = 0; i < 10; i++) {
28. String host = "127.0.0." + i;
29. long ts = System.currentTimeMillis();
30. double memUsage = i + 0.2;
31. memMetric.addRow(host, ts, memUsage);
32. }

或者我们可以使用 POJO 对象构建数据:

java

1. @Metric(name = "cpu_metric")
2. public class Cpu {
3. @Column(name = "host", tag = true, dataType = DataType.String)
4. private String host;

6. @Column(name = "ts", timestamp = true, dataType = DataType.TimestampMillisecond)
7. private long ts;

9. @Column(name = "cpu_user", dataType = DataType.Float64)
10. private double cpuUser;
11. @Column(name = "cpu_sys", dataType = DataType.Float64)
12. private double cpuSys;

14. // getters and setters
15. // ...
16. }

18. @Metric(name = "mem_metric")
19. public class Memory {
20. @Column(name = "host", tag = true, dataType = DataType.String)
21. private String host;

23. @Column(name = "ts", timestamp = true, dataType = DataType.TimestampMillisecond)
24. private long ts;

26. @Column(name = "mem_usage", dataType = DataType.Float64)
27. private double memUsage;
28. // getters and setters
29. // ...
30. }

32. // Add rows
33. List<Cpu> cpus = new ArrayList<>();
34. for (int i = 0; i < 10; i++) {
35. Cpu c = new Cpu();
36. c.setHost("127.0.0." + i);
37. c.setTs(System.currentTimeMillis());
38. c.setCpuUser(i + 0.1);
39. c.setCpuSys(i + 0.12);
40. cpus.add(c);
41. }

43. List<Memory> memories = new ArrayList<>();
44. for (int i = 0; i < 10; i++) {
45. Memory m = new Memory();
46. m.setHost("127.0.0." + i);
47. m.setTs(System.currentTimeMillis());
48. m.setMemUsage(i + 0.2);
49. memories.add(m);
50. }

保存行数据

下方的例子展示了如何将行数据保存到 GreptimeDB 中。

java

1. // Saves data

3. // For performance reasons, the SDK is designed to be purely asynchronous.
4. // The return value is a future object. If you want to immediately obtain
5. // the result, you can call `future.get()`.
6. CompletableFuture<Result<WriteOk, Err>> future = greptimeDB.write(cpuMetric, memMetric);

8. Result<WriteOk, Err> result = future.get();

10. if (result.isOk()) {
11. LOG.info("Write result: {}", result.getOk());
12. } else {
13. LOG.error("Failed to write: {}", result.getErr());
14. }

我们还可以使用 POJO 对象进行写入:

java

1. // Saves data

3. CompletableFuture<Result<WriteOk, Err>> puts = greptimeDB.writePOJOs(cpus, memories);

5. Result<WriteOk, Err> result = puts.get();

7. if (result.isOk()) {
8. LOG.info("Write result: {}", result.getOk());
9. } else {
10. LOG.error("Failed to write: {}", result.getErr());
11. }

更新行数据

请参考 更新数据了解更新机制。 下面的例子展示了先保存一行数据,然后更新这行数据。

java

1. Table cpuMetric = Table.from(myMetricCpuSchema);
2. // save a row data
3. long ts = 1703832681000L;
4. cpuMetric.addRow("host1", ts, 0.23, 0.12);
5. Result<WriteOk, Err> putResult = greptimeDB.write(cpuMetric).get();

7. // update the row data
8. Table newCpuMetric = Table.from(myMetricCpuSchema);
9. // The same tag `host1`
10. // The same time index `1703832681000`
11. // The new value: cpu_user = `0.80`, cpu_sys = `0.81`
12. long ts = 1703832681000L;
13. myMetricCpuSchema.addRow("host1", ts, 0.80, 0.81);

15. // overwrite the existing data
16. Result<WriteOk, Err> updateResult = greptimeDB.write(myMetricCpuSchema).get();

或者我们可以使用 POJO 对象进行更新:

java

1. Cpu cpu = new Cpu();
2. cpu.setHost("host1");
3. cpu.setTs(1703832681000L);
4. cpu.setCpuUser(0.23);
5. cpu.setCpuSys(0.12);

7. // save a row data
8. Result<WriteOk, Err> putResult = greptimeDB.writePOJOs(cpu).get();

10. // update the row data
11. Cpu newCpu = new Cpu();
12. // The same tag `host1`
13. newCpu.setHost("host1");
14. // The same time index `1703832681000`
15. newCpu.setTs(1703832681000L);
16. // The new value: cpu_user = `0.80`, cpu_sys = `0.81`
17. cpu.setCpuUser(0.80);
18. cpu.setCpuSys(0.81);

20. // overwrite the existing data
21. Result<WriteOk, Err> updateResult = greptimeDB.writePOJOs(newCpu).get();

请参考此处获取更多代码示例。

调试日志

ingester SDK 提供了用于调试的指标和日志。 请参考 Metrics & Display 和 Magic Tools 了解如何启用或禁用日志。

更多示例

请参考示例获取更多完全可运行的代码片段和常用方法的解释。

Ingester 库参考

查询数据

GreptimeDB 使用 SQL 作为主要查询语言,兼容 MySQL 和 PostgreSQL。 因此,我们推荐使用成熟的 SQL 驱动来查询数据。

推荐的查询库

Java 数据库连接(JDBC)是 JavaSoft 规范的标准应用程序编程接口(API),它允许 Java 程序访问数据库管理系统。

许多数据库,如 MySQL 或 PostgreSQL,都已经基于 JDBC API 实现了自己的驱动程序。 由于 GreptimeDB 支持多种协议,这里我们使用 MySQL 协议作为示例来演示如何使用 JDBC。 如果你希望使用其他协议,只需要将 MySQL 驱动程序替换为相应的驱动程序。

安装

如果你使用的是 Maven,请将以下内容添加到 pom.xml 的依赖项列表中:

xml

1. <!-- MySQL usage dependency -->
2. <dependency>
3. <groupId>mysql</groupId>
4. <artifactId>mysql-connector-java</artifactId>
5. <version>8.0.33</version>
6. </dependency>

连接到数据库

下方的例子展示了如何连接到 GreptimeDB:

这里我们使用 MySQL 作为示例来演示如何连接到 GreptimeDB。

java

2. public static Connection getConnection() throws IOException, ClassNotFoundException, SQLException {
3. Properties prop = new Properties();
4. prop.load(QueryJDBC.class.getResourceAsStream("/db-connection.properties"));

6. String dbName = (String) prop.get("db.database-driver");

8. String dbConnUrl = (String) prop.get("db.url");
9. String dbUserName = (String) prop.get("db.username");
10. String dbPassword = (String) prop.get("db.password");

12. Class.forName(dbName);
13. Connection dbConn = DriverManager.getConnection(dbConnUrl, dbUserName, dbPassword);

15. return Objects.requireNonNull(dbConn, "Failed to make connection!");
16. }

你需要一个 properties 文件来存储数据库连接信息,将其放在 Resources 目录中并命名为 db-connection.properties。文件内容如下:

txt

1. # DataSource
2. db.database-driver=com.mysql.cj.jdbc.Driver
3. db.url=jdbc:mysql://localhost:4002/public
4. db.username=
5. db.password=

或者你可以从这里获取文件。

Raw SQL

我们推荐使用 Raw SQL 来体验 GreptimeDB 的全部功能。 下面的例子展示了如何使用 Raw SQL 查询数据:

java

1. try (Connection conn = getConnection()) {
2. Statement statement = conn.createStatement();

4. // DESC table;
5. ResultSet rs = statement.executeQuery("DESC cpu_metric");
6. LOG.info("Column | Type | Key | Null | Default | Semantic Type ");
7. while (rs.next()) {
8. LOG.info("{} | {} | {} | {} | {} | {}", //
9. rs.getString(1), //
10. rs.getString(2), //
11. rs.getString(3), //
12. rs.getString(4), //
13. rs.getString(5), //
14. rs.getString(6));
15. }

17. // SELECT COUNT(*) FROM cpu_metric;
18. rs = statement.executeQuery("SELECT COUNT(*) FROM cpu_metric");
19. while (rs.next()) {
20. LOG.info("Count: {}", rs.getInt(1));
21. }

23. // SELECT * FROM cpu_metric ORDER BY ts DESC LIMIT 5;
24. rs = statement.executeQuery("SELECT * FROM cpu_metric ORDER BY ts DESC LIMIT 5");
25. LOG.info("host | ts | cpu_user | cpu_sys");
26. while (rs.next()) {
27. LOG.info("{} | {} | {} | {}", //
28. rs.getString("host"), //
29. rs.getTimestamp("ts"), //
30. rs.getDouble("cpu_user"), //
31. rs.getDouble("cpu_sys"));
32. }
33. }

请参考此处获取更多可执行代码。

查询库参考

有关如何使用查询库的更多信息,请参考相应库的文档: