Use the ApsaraDB for Lindorm SDK to write multiple values

Updated at:
Copy as MD

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:

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.

Important

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:

ComponentDescriptionExample
MetricCategory of measurement. Similar to a measurement in InfluxDB."wind"
FieldSub-category under a metric. A metric can have multiple fields."speed", "direction"
TagMetadata attached to a time series."city", "province"
TimestampUnix 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

ParameterDescriptionExample value
batchPutSizeNumber of data points submitted per batch500
batchPutConsumerThreadCountThreads processing asynchronous single-value writes1
multiFieldBatchPutBufferSizeSize of the cache queue for asynchronous multi-value writes10000
multiFieldBatchPutConsumerThreadCountThreads processing asynchronous multi-value writes1
httpConnectTimeoutHTTP connection timeout in seconds90
listenMultiFieldBatchPutRegisters a callback to receive asynchronous write resultscallback 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 typeClassresponse() returnsBest for
None——Maximum throughput, no confirmation needed
CommonMultiFieldBatchPutCallbackWritten points or failed points + exceptionBasic success/failure tracking
SummaryMultiFieldBatchPutSummaryCallbackPoints + success/failure counts (SummaryResult)Monitoring write success rates
DetailMultiFieldBatchPutDetailsCallbackPoints + per-point failure list (DetailsResult)Identifying and retrying specific failed points

What's next