Use the ApsaraDB for Lindorm SDK to write multiple values
The Lindorm SDK's multi-value model lets you write multiple fields under a single metric in one operation. This page shows how to write data points using the Java SDK, covering synchronous writes and four asynchronous write variants.
Choose a write mode:
Synchronous write — blocking call, immediate error feedback
Asynchronous write without a callback — fire-and-forget batch
Asynchronous write with a common callback — per-batch success/failure notification
Asynchronous write with a summary callback — per-batch counts of successful and failed points
Asynchronous write with a detail callback — per-batch list of failed points with error details
For complete example code, see the Aliyun TSDB SDK for Java repository, specifically the test/example/SampleOfMultiField and test/TestHiTSDBClientMultiFieldFeatures directories.
Prerequisites
Before you begin, ensure that you have:
Lindorm SDK V0.2.0 or later. Versions earlier than V0.2.0 use a simulated multi-value model, which is not recommended. For the latest SDK version and download link, see the "Versions" section in the SDK documentation.
Lindorm SDK V0.2.1 or later for asynchronous writes.
Data written using the MultiField class of SDK V0.2.0 or later cannot be queried using the MultiValue class of an earlier SDK version.
Key concepts
A MultiFieldPoint represents one data point and contains the following components:
| Component | Description | Example |
|---|---|---|
| Metric | Category of measurement. Similar to a measurement in InfluxDB. | "wind" |
| Field | Sub-category under a metric. A metric can have multiple fields. | "speed", "direction" |
| Tag | Metadata attached to a time series. | "city", "province" |
| Timestamp | Unix timestamp of the data point (seconds). | 1537170208L |
Synchronous write
Use multiFieldPutSync() when you need immediate confirmation that a write succeeded before proceeding. The call blocks until the server acknowledges the write. This method supports both single-point and multi-point writes.
/*
* Build a data point with multiple fields.
*
* Metric: "wind" - the category being measured
* Fields: speed, level, direction, description - sub-measurements
* Tags: sensor, city, province - metadata identifying the time series
* Timestamp: Unix time in seconds
*/
MultiFieldPoint multiFieldPoint = MultiFieldPoint.metric("wind")
.field("speed", 45.2)
.field("level", 1.2)
.field("direction", "S")
.field("description", "Breeze")
.tag("sensor", "95D8-7913")
.tag("city", "hangzhou")
.tag("province", "zhejiang")
.timestamp(1537170208L)
.build();
tsdb.multiFieldPutSync(multiFieldPoint);Asynchronous writes
All asynchronous write variants share the same client initialization and shutdown pattern. Initialize the Time Series Database (TSDB) client once for the lifecycle of your application and close it only when the application exits.
TSDBConfig parameters for asynchronous writes
| Parameter | Description | Example value |
|---|---|---|
batchPutSize | Number of data points submitted per batch | 500 |
batchPutConsumerThreadCount | Threads processing asynchronous single-value writes | 1 |
multiFieldBatchPutBufferSize | Size of the cache queue for asynchronous multi-value writes | 10000 |
multiFieldBatchPutConsumerThreadCount | Threads processing asynchronous multi-value writes | 1 |
httpConnectTimeout | HTTP connection timeout in seconds | 90 |
listenMultiFieldBatchPut | Registers a callback to receive asynchronous write results | callback instance |
Asynchronous write without a callback
Use this mode when throughput is the priority and you do not need per-batch confirmation.
TSDBConfig config = TSDBConfig.address("127.0.0.1", 8242)
.batchPutSize(500)
.batchPutConsumerThreadCount(1)
.multiFieldBatchPutBufferSize(10000)
.multiFieldBatchPutConsumerThreadCount(1)
.config();
// Initialize the client once. Reuse this instance throughout your application.
TSDB tsdb = TSDBClientFactory.connect(config);
MultiFieldPoint point = MultiFieldPoint
.metric("test-test-test")
.tag("a", "1")
.tag("b", "2")
.timestamp(System.currentTimeMillis())
.field("f1", Math.random())
.field("f2", Math.random())
.build();
tsdb.multiFieldPut(point);
// Close the client only when the application exits.
tsdb.close();Asynchronous write with a common callback
Use this mode when you need to know whether each batch succeeded or failed, without per-point detail. The callback receives either the successfully written points or the failed points with the associated exception.
// The common callback reports batch-level success or failure.
AbstractMultiFieldBatchPutCallback callback = new MultiFieldBatchPutCallback() {
final AtomicInteger num = new AtomicInteger();
@Override
public void response(String address, List<MultiFieldPoint> points, Result result) {
int count = num.addAndGet(points.size());
System.out.println(result);
System.out.println("Processed " + count + " points.");
}
@Override
public void failed(String address, List<MultiFieldPoint> points, Exception ex) {
System.err.println("Batch failed: " + points.size() + " points. Error:");
ex.printStackTrace();
}
};
TSDBConfig config = TSDBConfig.address("127.0.0.1", 8242)
.httpConnectTimeout(90)
.batchPutSize(500)
.batchPutConsumerThreadCount(1)
.multiFieldBatchPutBufferSize(10000)
.multiFieldBatchPutConsumerThreadCount(1)
.listenMultiFieldBatchPut(callback)
.config();
TSDB tsdb = TSDBClientFactory.connect(config);
MultiFieldPoint point = MultiFieldPoint
.metric("test-test-test")
.tag("a", "1")
.tag("b", "2")
.timestamp(System.currentTimeMillis())
.field("f1", Math.random())
.field("f2", Math.random())
.build();
tsdb.multiFieldPut(point);
tsdb.close();Asynchronous write with a summary callback
Use this mode when you need a count of successful and failed points per batch, but not the details of individual failures. On success, the callback receives the points and a SummaryResult with success and failure counts. On failure, it receives the points and the exception.
// The summary callback reports counts of successful and failed points per batch.
AbstractMultiFieldBatchPutCallback callback = new MultiFieldBatchPutSummaryCallback() {
final AtomicInteger num = new AtomicInteger();
@Override
public void response(String address, List<MultiFieldPoint> points, SummaryResult result) {
int count = num.addAndGet(points.size());
System.out.println(result);
System.out.println("Processed " + count + " points.");
}
@Override
public void failed(String address, List<MultiFieldPoint> points, Exception ex) {
System.err.println("Batch failed: " + points.size() + " points. Error:");
ex.printStackTrace();
}
};
TSDBConfig config = TSDBConfig.address("127.0.0.1", 8242)
.httpConnectTimeout(90)
.batchPutSize(500)
.batchPutConsumerThreadCount(1)
.multiFieldBatchPutBufferSize(10000)
.multiFieldBatchPutConsumerThreadCount(1)
.listenMultiFieldBatchPut(callback)
.config();
TSDB tsdb = TSDBClientFactory.connect(config);
MultiFieldPoint point = MultiFieldPoint
.metric("test-test-test")
.tag("a", "1")
.tag("b", "2")
.timestamp(System.currentTimeMillis())
.field("f1", Math.random())
.field("f2", Math.random())
.build();
tsdb.multiFieldPut(point);
tsdb.close();Asynchronous write with a detail callback
Use this mode when you need to identify and retry individual failed points. On success, the callback receives the points and a DetailsResult containing each failed point and its error. On failure, it receives the points and the exception.
// The detail callback identifies which individual points failed and why.
MultiFieldBatchPutDetailsCallback callback = new MultiFieldBatchPutDetailsCallback() {
final AtomicInteger num = new AtomicInteger();
@Override
public void response(String address, List<MultiFieldPoint> points, DetailsResult result) {
int count = num.addAndGet(points.size());
System.out.println(result);
System.out.println("Processed " + count + " points.");
}
@Override
public void failed(String address, List<MultiFieldPoint> points, Exception ex) {
System.err.println("Batch failed: " + points.size() + " points. Error:");
ex.printStackTrace();
}
};
TSDBConfig config = TSDBConfig.address("127.0.0.1", 8242)
.httpConnectTimeout(90)
.batchPutSize(500)
.batchPutConsumerThreadCount(1)
.multiFieldBatchPutBufferSize(10000)
.multiFieldBatchPutConsumerThreadCount(1)
.listenMultiFieldBatchPut(callback)
.config();
TSDB tsdb = TSDBClientFactory.connect(config);
MultiFieldPoint point = MultiFieldPoint
.metric("test-test-test")
.tag("a", "1")
.tag("b", "2")
.timestamp(System.currentTimeMillis())
.field("f1", Math.random())
.field("f2", Math.random())
.build();
tsdb.multiFieldPut(point);
tsdb.close();Choose a callback type
| Callback type | Class | response() returns | Best for |
|---|---|---|---|
| None | — | — | Maximum throughput, no confirmation needed |
| Common | MultiFieldBatchPutCallback | Written points or failed points + exception | Basic success/failure tracking |
| Summary | MultiFieldBatchPutSummaryCallback | Points + success/failure counts (SummaryResult) | Monitoring write success rates |
| Detail | MultiFieldBatchPutDetailsCallback | Points + per-point failure list (DetailsResult) | Identifying and retrying specific failed points |