Java Ingester for GreptimeDB
GreptimeDB 提供了用于高吞吐量数据写入的 ingester 库。 它使用 gRPC 协议,支持无 schema 写入,无需在写入数据前创建表。 更多信息请参考 自动生成表结构。
GreptimeDB 提供的 Java ingester SDK 是一个轻量级、高性能的客户端,专为高效的时间序列数据写入而设计。它利用 gRPC 协议提供非阻塞、纯异步的 API,在保持与应用程序无缝集成的同时提供高吞吐数据写入。
该客户端提供针对各种性能要求和使用场景优化的多种写入方法。你可以选择最适合你特定需求的方法——无论你需要低延迟操作的简单一元写入,还是处理大量时间序列数据时最大效率的高吞吐量批量流式传输。
架构
+-----------------------------------+
| Client Applications |
| +------------------+ |
| | Application Code | |
| +------------------+ |
+-------------+---------------------+
|
v
+-------------+---------------------+
| API Layer |
| +---------------+ |
| | GreptimeDB | |
| +---------------+ |
| / \ |
| v v |
| +-------------+ +-------------+ | +------------------+
| | BulkWrite | | Write | | | Data Model |
| | Interface | | Interface | |------->| |
| +-------------+ +-------------+ | | +------------+ |
+-------|----------------|----------+ | | Table | |
| | | +------------+ |
v v | | |
+-------|----------------|----------+ | v |
| Transport Layer | | +------------+ |
| +-------------+ +-------------+ | | | TableSchema| |
| | BulkWrite | | Write | | | +------------+ |
| | Client | | Client | | +------------------+
| +-------------+ +-------------+ |
| | \ / | |
| | \ / | |
| | v v | |
| | +-------------+ | |
| | |RouterClient | | |
+-----|--+-------------|---+--------+
| | | |
| | | |
v v v |
+-----|----------------|---|--------+
| Network Layer |
| +-------------+ +-------------+ |
| | Arrow Flight| | gRPC Client | |
| | Client | | | |
| +-------------+ +-------------+ |
| | | |
+-----|----------------|------------+
| |
v v
+-------------------------+
| GreptimeDB Server |
+-------------------------+
- API Layer:为客户端应用程序提供与 GreptimeDB 交互的上层接口
- Data Model:定义时间序列数据的结构和组织,包括表和 schemas
- Transport Layer:处理通信逻辑、请求路由和客户端管理
- Network Layer:使用 Arrow Flight 和 gRPC 底层协议通信
使用方法
安装
- 安装 Java 开发工具包(JDK)
确保你的系统已安装 JDK 8 或更高版本。有关如何检查 Java 版本并安装 JDK 的更多信息,请参见 Oracle JDK 安装概述文档
- 将 GreptimeDB Java SDK 添加为依赖项
如果你使用的是 Maven,请将以下内容添加到 pom.xml 的依赖项列表中:
<dependency>
<groupId>io.greptime</groupId>
<artifactId>ingester-all</artifactId>
<version>0.15.0</version>
</dependency>
最新版本可以在 这里 查看。
配置依赖项后,请确保它们对项目可用。这可能需要在 IDE 中刷新项目或运行依赖项管理器。
客户端初始化
GreptimeDB Ingester Java 客户端的入口点是 GreptimeDB 类。你可以通过调用静态创建方法并传入适当的配置选项来创建客户端实例。
// GreptimeDB 在默认目录 "greptime" 中有一个名为 "public" 的默认数据库,
// 我们可以将其用作测试数据库
String database = "public";
// 默认情况下,GreptimeDB 使用 gRPC 协议在端口 4001 上监听。
// 我们可以提供多个指向同一 GreptimeDB 集群的端点。
// 客户端将基于负载均衡策略调用这些端点。
// 客户端执行定期健康检查并自动将请求路由到健康节点,
// 为你的应用程序提供容错能力和改进的可靠性。
String[] endpoints = {"127.0.0.1:4001"};
// 设置认证信息。
AuthInfo authInfo = new AuthInfo("username", "password");
GreptimeOptions opts = GreptimeOptions.newBuilder(endpoints, database)
// 如果数据库不需要认证,我们可以使用 `AuthInfo.noAuthorization()` 作为参数。
.authInfo(authInfo)
// 如果你的服务器由 TLS 保护,请启用安全连接
//.tlsOptions(new TlsOptions())
// 好的开始 ^_^
.build();
// 初始化客户端
// 注意:客户端实例是线程安全的,应作为全局单例重用
// 以获得更好的性能和资源利用率。
GreptimeDB client = GreptimeDB.create(opts);
写入数据
Ingester 通过 Table 抽象为写入数据到 GreptimeDB 提供了统一的方法。所有数据写入操作,包括高级 API,都建立在这个基础结构之上。要写入数据,你需要创建一个 Table 为其填充时间序列数据,最后将其写入数据库。
创建和写入表
定义表结构并创建表:
// 创建表结构
TableSchema schema = TableSchema.newBuilder("metrics")
.addTag("host", DataType.String)
.addTag("region", DataType.String)
.addField("cpu_util", DataType.Float64)
.addField("memory_util", DataType.Float64)
.addTimestamp("ts", DataType.TimestampMillisecond)
.build();
// 从 schema 创建表数据容器
Table table = Table.from(schema);
// 向表中添加行
// 值必须按照结构中定义的顺序提供
// 在这种情况下:addRow(host, region, cpu_util, memory_util, ts)
table.addRow("host1", "us-west-1", 0.42, 0.78, System.currentTimeMillis());
table.addRow("host2", "us-west-2", 0.46, 0.66, System.currentTimeMillis());
// 添加更多行
// ..
// 把表标记为完成以使其不可变。这将最终确定表的数据内容以进行写入。
// 如果你忘记了调用此方法,它将在表数据写入前自动在内部调用
table.complete();
// 写入数据库
CompletableFuture<Result<WriteOk, Err>> future = client.write(table);
GreptimeDB 支持使用 JSON 类型数据 存储复杂的数据结构。你可以在表结构中定义 JSON 列,并使用 Map 对象插入数据:
// 为 sensor_readings 构建表结构
TableSchema sensorReadings = TableSchema.newBuilder("sensor_readings")
// 省略创建其他列的代码
// ...
// 将列类型指定为 JSON
.addField("attributes", DataType.Json)
.build();
// ...
// 使用 map 插入 JSON 数据
Map<String, Object> attr = new HashMap<>();
attr.put("location", "factory-1");
Table table = Table.from(sensorReadings);
table.addRow(<other-column-values>... , attr);
TableSchema
TableSchema 定义了写入数据到 GreptimeDB 的结构。它指定表结构,包括列名、语义类型和数据类型。有关列语义类型(Tag、Timestamp、Field)的详细信息,请参考 数据模型 文档。
Table
Table 接口表示可以写入到 GreptimeDB 的数据。它提供添加行和操作数据的方法。本质上,Table 将数据临时存储在内存中,允许你在将数据发送到数据库之前累积多行进行批处理,这比写入单个行显著提高了写入效率。
表经历几个不同的生命周期阶段:
- 创建:使用
Table.from(schema)从 schema 初始化表 - 数据添加:使用
addRow()方法用行填充表 - 完成:添加所有行后使用
complete()冻结表不允许再修改 - 写入:将完成的表发送到数据库
重要提醒:
- 表不是线程安全的,应该单线程访问
- 写入后不能重用表 - 需要为每个写入操作创建新实例
- 关联的
TableSchema是不可变的,可以在多个操作中安全地复用
写入操作
虽然在通过 SDK 向 GreptimeDB 写入数据时会自动创建时间序列表, 但你仍然可以配置表选项。 SDK 支持以下表选项:
auto_create_table:默认为True。如果设置为False,表示表已经存在且不需要自动创建,这可以提高写入性能。ttl、append_mode、merge_mode:更多详情请参考 表选项。
你可以使用 Context 设置表选项。
例如,要设置 ttl 选项,请使用以下代码:
Context ctx = Context.newDefault();
// 添加提示使数据库创建具有指定 TTL(生存时间)的表
ctx = ctx.withHint("ttl", "3d");
// 将压缩算法设置为 Zstd。
ctx = ctx.withCompression(Compression.Zstd);
// 写入数据到 GreptimeDB 时使用 ctx
CompletableFuture<Result<WriteOk, Err>> future = client.write(Arrays.asList(table1, table2), WriteOp.Insert, ctx);
有关如何向 GreptimeDB 写入数据,请参阅以下部分。