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();
  15. GreptimeDB client = GreptimeDB.create(opts);

行对象

表中的每条行数据包含三种类型的列:TagTimestampField。更多信息请参考 数据模型。 列值的类型可以是 StringFloatIntTimestamp 等。更多信息请参考 数据类型

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

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

创建行数据

下面的例子展示了如何创建包含 TagTimestampField 列的行。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);
  9. String host = "127.0.0.1";
  10. long ts = System.currentTimeMillis();
  11. double cpuUser = 0.1;
  12. double cpuSys = 0.12;
  13. 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();
  8. TableSchema memMetricSchema = TableSchema.newBuilder("mem_metric") //
  9. .addColumn("host", SemanticType.Tag, DataType.String) //
  10. .addColumn("ts", SemanticType.Timestamp, DataType.TimestampMillisecond) //
  11. .addColumn("mem_usage", SemanticType.Field, DataType.Float64) //
  12. .build();
  13. Table cpuMetric = Table.from(cpuMetricSchema);
  14. Table memMetric = Table.from(memMetricSchema);
  15. // Adds row data items
  16. for (int i = 0; i < 10; i++) {
  17. String host = "127.0.0." + i;
  18. long ts = System.currentTimeMillis();
  19. double cpuUser = i + 0.1;
  20. double cpuSys = i + 0.12;
  21. cpuMetric.addRow(host, ts, cpuUser, cpuSys);
  22. }
  23. for (int i = 0; i < 10; i++) {
  24. String host = "127.0.0." + i;
  25. long ts = System.currentTimeMillis();
  26. double memUsage = i + 0.2;
  27. memMetric.addRow(host, ts, memUsage);
  28. }

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

java

  1. @Metric(name = "cpu_metric")
  2. public class Cpu {
  3. @Column(name = "host", tag = true, dataType = DataType.String)
  4. private String host;
  5. @Column(name = "ts", timestamp = true, dataType = DataType.TimestampMillisecond)
  6. private long ts;
  7. @Column(name = "cpu_user", dataType = DataType.Float64)
  8. private double cpuUser;
  9. @Column(name = "cpu_sys", dataType = DataType.Float64)
  10. private double cpuSys;
  11. // getters and setters
  12. // ...
  13. }
  14. @Metric(name = "mem_metric")
  15. public class Memory {
  16. @Column(name = "host", tag = true, dataType = DataType.String)
  17. private String host;
  18. @Column(name = "ts", timestamp = true, dataType = DataType.TimestampMillisecond)
  19. private long ts;
  20. @Column(name = "mem_usage", dataType = DataType.Float64)
  21. private double memUsage;
  22. // getters and setters
  23. // ...
  24. }
  25. // Add rows
  26. List<Cpu> cpus = new ArrayList<>();
  27. for (int i = 0; i < 10; i++) {
  28. Cpu c = new Cpu();
  29. c.setHost("127.0.0." + i);
  30. c.setTs(System.currentTimeMillis());
  31. c.setCpuUser(i + 0.1);
  32. c.setCpuSys(i + 0.12);
  33. cpus.add(c);
  34. }
  35. List<Memory> memories = new ArrayList<>();
  36. for (int i = 0; i < 10; i++) {
  37. Memory m = new Memory();
  38. m.setHost("127.0.0." + i);
  39. m.setTs(System.currentTimeMillis());
  40. m.setMemUsage(i + 0.2);
  41. memories.add(m);
  42. }

保存行数据

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

java

  1. // Saves data
  2. // For performance reasons, the SDK is designed to be purely asynchronous.
  3. // The return value is a future object. If you want to immediately obtain
  4. // the result, you can call `future.get()`.
  5. CompletableFuture<Result<WriteOk, Err>> future = greptimeDB.write(cpuMetric, memMetric);
  6. Result<WriteOk, Err> result = future.get();
  7. if (result.isOk()) {
  8. LOG.info("Write result: {}", result.getOk());
  9. } else {
  10. LOG.error("Failed to write: {}", result.getErr());
  11. }

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

java

  1. // Saves data
  2. CompletableFuture<Result<WriteOk, Err>> puts = greptimeDB.writePOJOs(cpus, memories);
  3. Result<WriteOk, Err> result = puts.get();
  4. if (result.isOk()) {
  5. LOG.info("Write result: {}", result.getOk());
  6. } else {
  7. LOG.error("Failed to write: {}", result.getErr());
  8. }

更新行数据

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

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();
  6. // update the row data
  7. Table newCpuMetric = Table.from(myMetricCpuSchema);
  8. // The same tag `host1`
  9. // The same time index `1703832681000`
  10. // The new value: cpu_user = `0.80`, cpu_sys = `0.81`
  11. long ts = 1703832681000L;
  12. myMetricCpuSchema.addRow("host1", ts, 0.80, 0.81);
  13. // overwrite the existing data
  14. 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);
  6. // save a row data
  7. Result<WriteOk, Err> putResult = greptimeDB.writePOJOs(cpu).get();
  8. // update the row data
  9. Cpu newCpu = new Cpu();
  10. // The same tag `host1`
  11. newCpu.setHost("host1");
  12. // The same time index `1703832681000`
  13. newCpu.setTs(1703832681000L);
  14. // The new value: cpu_user = `0.80`, cpu_sys = `0.81`
  15. cpu.setCpuUser(0.80);
  16. cpu.setCpuSys(0.81);
  17. // overwrite the existing data
  18. Result<WriteOk, Err> updateResult = greptimeDB.writePOJOs(newCpu).get();

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

调试日志

ingester SDK 提供了用于调试的指标和日志。 请参考 Metrics & DisplayMagic 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

  1. public static Connection getConnection() throws IOException, ClassNotFoundException, SQLException {
  2. Properties prop = new Properties();
  3. prop.load(QueryJDBC.class.getResourceAsStream("/db-connection.properties"));
  4. String dbName = (String) prop.get("db.database-driver");
  5. String dbConnUrl = (String) prop.get("db.url");
  6. String dbUserName = (String) prop.get("db.username");
  7. String dbPassword = (String) prop.get("db.password");
  8. Class.forName(dbName);
  9. Connection dbConn = DriverManager.getConnection(dbConnUrl, dbUserName, dbPassword);
  10. return Objects.requireNonNull(dbConn, "Failed to make connection!");
  11. }

你需要一个 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();
  3. // DESC table;
  4. ResultSet rs = statement.executeQuery("DESC cpu_metric");
  5. LOG.info("Column | Type | Key | Null | Default | Semantic Type ");
  6. while (rs.next()) {
  7. LOG.info("{} | {} | {} | {} | {} | {}", //
  8. rs.getString(1), //
  9. rs.getString(2), //
  10. rs.getString(3), //
  11. rs.getString(4), //
  12. rs.getString(5), //
  13. rs.getString(6));
  14. }
  15. // SELECT COUNT(*) FROM cpu_metric;
  16. rs = statement.executeQuery("SELECT COUNT(*) FROM cpu_metric");
  17. while (rs.next()) {
  18. LOG.info("Count: {}", rs.getInt(1));
  19. }
  20. // SELECT * FROM cpu_metric ORDER BY ts DESC LIMIT 5;
  21. rs = statement.executeQuery("SELECT * FROM cpu_metric ORDER BY ts DESC LIMIT 5");
  22. LOG.info("host | ts | cpu_user | cpu_sys");
  23. while (rs.next()) {
  24. LOG.info("{} | {} | {} | {}", //
  25. rs.getString("host"), //
  26. rs.getTimestamp("ts"), //
  27. rs.getDouble("cpu_user"), //
  28. rs.getDouble("cpu_sys"));
  29. }
  30. }

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

查询库参考

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