diff --git a/README.md b/README.md index 065e074..59044e8 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,190 @@ -# ceresdb-java-client -Java client for CeresDB +# CeresDB Java Client +[中文](./README_CN.md) + +## Introduction +CeresDBxClient is a high-performance Java client for CeresDB. +CeresDB is a high-performance, distributed, schema-less, cloud native time-series database that can handle both time-series and analytics workloads. + +## Features +- With the well designed SPI, the network transport layer is extensible. And we provide the default implementation which uses the gRPC framework. +- The client provides high-performance async streaming write API. +- The client also collects lots of performance metrics by default. These metrics can be configured to write to local file. +- We can take memory snapshots that contains the status of critical objects. The snapshots can also be configured to write to local file, which helps a lot when we diagnose complex problems. + +## Data ingestion process + +``` + ┌─────────────────────┐ + │ CeresDBxClient │ + └─────────────────────┘ + │ + ▼ + ┌─────────────────────┐ + │ WriteClient │───┐ + └─────────────────────┘ │ + │ Async to retry and merge responses + │ │ + ┌────Split requests │ + │ │ + │ ┌─────────────────────┐ │ ┌─────────────────────┐ ┌─────────────────────┐ + └─▶│ RouterClient │◀─┴──▶│ RouterCache │◀─────▶│ RouterFor │ + └─────────────────────┘ └─────────────────────┘ └─────────────────────┘ + ▲ │ + │ │ + ▼ │ + ┌─────────────────────┐ │ + │ RpcClient │◀──────────────────────────────────────────────┘ + └─────────────────────┘ + ▲ + │ + ▼ + ┌─────────────────────┐ + │ Default gRPC impl │ + └─────────────────────┘ + ▲ + │ + ┌───────────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ + │ │ + ▼ ▼ ▼ +┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐ +│ CeresDBx Node1 │ │ CeresDBx Node2 │ │ ... │ +└─────────────────────┘ └─────────────────────┘ └─────────────────────┘ +``` + +## Data query process +``` + ┌─────────────────────┐ + │ CeresDBxClient │ + └─────────────────────┘ + │ + ▼ + ┌─────────────────────┐ + │ QueryClient │───┐ + └─────────────────────┘ │ + │ │Async to retry + │ │ + ┌────────────┘ │ + │ │ + │ ┌─────────────────────┐ │ ┌─────────────────────┐ ┌─────────────────────┐ + └─▶│ RouterClient │◀─┴──▶│ RouterCache │◀─────▶│ RouterFor │ + └─────────────────────┘ └─────────────────────┘ └─────────────────────┘ + ▲ │ + │ │ + ▼ │ + ┌─────────────────────┐ │ + │ RpcClient │◀──────────────────────────────────────────────┘ + └─────────────────────┘ + ▲ + │ + ▼ + ┌─────────────────────┐ + │ Default gRPC impl │ + └─────────────────────┘ + ▲ + │ + ┌───────────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ + │ │ + ▼ ▼ ▼ +┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐ +│ CeresDBx Node1 │ │ CeresDBx Node2 │ │ ... │ +└─────────────────────┘ └─────────────────────┘ └─────────────────────┘ +``` + +## Requirements +- Java 8 or later is required for compilation + + +## Create table +CeresDB is a Schema-less time-series database, so creating table schema ahead of data ingestion is not required (CeresDB will create a default schema according to the very first data you write into it). Of course, you can also manually create a schema for fine grained management purposes (eg. managing index). + +The following table creation statement(using the SQL API included in SDK )shows all field types supported by CeresDB: + +```java +SqlResult result = client.management().executeSql("CREATE TABLE MY_FIRST_TABL(" + + "ts TIMESTAMP NOT NULL," + + "c1 STRING TAG NOT NULL," + + "c2 STRING TAG NOT NULL," + + "c3 DOUBLE NULL," + + "c4 STRING NULL," + + "c5 INT64 NULL," + + "c6 FLOAT NULL," + + "c7 INT32 NULL," + + "c8 INT16 NULL," + + "c9 INT8 NULL," + + "c10 BOOLEAN NULL," + "c11 UINT64 NULL," + "c12 UINT32 NULL," + "c13 UINT16 NULL," + "c14 UINT8 NULL," + "c15 TIMESTAMP NULL," + "c16 VARBINARY NULL," + "TIMESTAMP KEY(ts)) ENGINE=Analytic" +); +``` + +## Data ingestion example +```java +// CeresDBx options +final CeresDBxOptions opts = CeresDBxOptions.newBuilder("127.0.0.1", 8081) // + .tenant("test", "sub_test", "test_token") // tenant info + // maximum retry times when write fails + // (only some error codes will be retried, such as the routing table failure) + .writeMaxRetries(1) + // maximum retry times when read fails + // (only some error codes will be retried, such as the routing table failure) + .readMaxRetries(1) + .build(); + +final CeresDBxClient client = new CeresDBxClient(); +if (!client.init(this.opts)) { + throw new IllegalStateException("Fail to start CeresDBxClient"); +} + +final long t0 = System.currentTimeMillis(); +final long t1 = t0 + 1000; +final long t2 = t1 + 1000; +final Rows data = Series.newBuilder("machine_metric") + .tag("city", "Singapore") + .tag("ip", "127.0.01") + .toRowsBuilder() + // codes below organizes 3 lines data (3 timestamps) for the `cpu` and `mem` column, this will just transport once through network. CeresDB encourage practices like this, because the SDK could use efficient compression algorithm to reduce network overhead and also be friedly to the sever side. + .field(t0, "cpu", FieldValue.withDouble(0.23)) // first row, first column + .field(t0, "mem", FieldValue.withDouble(0.55)) // first row, second column + .field(t1, "cpu", FieldValue.withDouble(0.25)) // second row, first column + .field(t1, "mem", FieldValue.withDouble(0.56)) // second row, second column + .field(t2, "cpu", FieldValue.withDouble(0.21)) // third row, first column + .field(t2, "mem", FieldValue.withDouble(0.52)) // third row, second column + .build(); + +final CompletableFuture> wf = client.write(data); +// here the `future.get` is just for demonstration, a better async programming practice would be using the CompletableFuture API +final Result wr = wf.get(); + +Assert.assertTrue(wr.isOk()); +Assert.assertEquals(3, wr.getOk().getSuccess()); +// `Result` class referenced the Rust language practice, provides rich functions (such as mapXXX, andThen) transforming the result value to improve programming efficiency. You can refer to the API docs for detail usage. +Assert.assertEquals(3, wr.mapOr(0, WriteOk::getSuccess())); +Assert.assertEquals(0, wr.getOk().getFailed()); +Assert.assertEquals(0, wr.mapOr(-1, WriteOk::getFailed)); + +final QueryRequest queryRequest = QueryRequest.newBuilder() + .forMetrics("machine_metric") // table name is optional. If not provided, SQL parser will parse the `ql` to get the table name and do the routing automaticly + .ql("select timestamp, cpu, mem from machine_metric") // + .build(); +final CompletableFuture> qf = client.query(queryRequest); +// here the `future.get` is just for demonstration, a better async programming practice would be using the CompletableFuture API +final Result qr = qf.get(); + +Assert.assertTrue(qr.isOk()); + +final QueryOk queryOk = qr.getOk(); + +final List records = queryOk.mapToRecord().collect(Collectors.toList()) +``` +## Licensing +Under [Apache License 2.0](./LICENSE). + +## Community and support +- Join the user group on [Slack](https://join.slack.com/t/ceresdbcommunity/shared_invite/zt-1au1ihbdy-5huC9J9s2462yBMIWmerTw) +- Join the use group on WeChat [WeChat QR code](https://github.com/CeresDB/assets/blob/main/WeChatQRCode.jpg) +- Join the user group on DingTalk: 44602802 diff --git a/docs/README.md b/README_CN.md similarity index 93% rename from docs/README.md rename to README_CN.md index 959fe84..5f338c4 100644 --- a/docs/README.md +++ b/README_CN.md @@ -1,5 +1,7 @@ -# CeresDB client -CeresDBxClient 是 CeresDB 的高性能 Java 版客户端,CeresDB 定位高性能的、分布式的、Schema-less 的 HTAP (Hybrid Timeseries/Analytic Processing) 型时间序列数据库。 +# CeresDB Java Client + +## 介绍 +CeresDBxClient 是 CeresDB 的高性能 Java 版客户端。CeresDB 是定位为高性能的、分布式的、Schema-less 的云原生时序数据库。它可以同时支持时间序列和数据分析型的工作负载。 ## 功能特性 - 通信层基于 SPI 可扩展,默认提供 gRPC 的实现 @@ -87,7 +89,7 @@ CeresDBxClient 是 CeresDB 的高性能 Java 版客户端,CeresDB 定位高性 ``` ## 需要 -编译需要 Java8 及以上 +编译需要 Java 8 及以上 ## 建表 CeresDB 是一个 Schema-less 的时序数据引擎,你可以不必创建 schema 就立刻写入数据(CeresDB 会根据你的第一次写入帮你创建一个默认的 schema)。 @@ -118,8 +120,6 @@ SqlResult result = client.management().executeSql("CREATE TABLE MY_FIRST_TABL(" ); ``` -更多建表语句例子见 [这里](./table.md) - ## 写入 Example ```java // CeresDBx options @@ -138,7 +138,7 @@ final long t0 = System.currentTimeMillis(); final long t1 = t0 + 1000; final long t2 = t1 + 1000; final Rows data = Series.newBuilder("machine_metric") - .tag("city", "Hangzhou") + .tag("city", "Singapore") .tag("ip", "127.0.01") .toRowsBuilder() // 下面针对 cpu、mem 两列,一次写入了三行数据(3 个时间戳),CeresDB 鼓励这种实践,SDK 可以通过高效的压缩来减少网络传输,并且对 server 端写入非常友好 @@ -176,5 +176,10 @@ final QueryOk queryOk = qr.getOk(); final List records = queryOk.mapToRecord().collect(Collectors.toList()) ``` -## 技术支持 -- 顾客是上帝钉钉群:21983792 +## Licensing +遵守 [Apache License 2.0](./LICENSE). + +## 社区与技术支持 +- 加入 Slack 社区与用户群 [Slack 入口](https://join.slack.com/t/ceresdbcommunity/shared_invite/zt-1au1ihbdy-5huC9J9s2462yBMIWmerTw) +- 加入微信社区与用户群 [微信二维码](https://github.com/CeresDB/assets/blob/main/WeChatQRCode.jpg) +- 搜索并加入钉钉社区与用户群 44602802