涛思数据TDengine now插值问题记录

TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传递的 PRECISION 参数就可以支持微秒和纳秒。(从 2.1.5.0 版本开始支持纳秒精度)。在使用过程中如果没有特殊要求一般采用默认值。

TDengine内部函数 now 是客户端的当前时间,插入记录时,如果时间戳为 now,插入数据时使用提交这条记录的客户端的当前时间。在使用“插入多条记录”方式写入数据时,不能把第一列的时间戳取值都设为 NOW,否则会导致语句中的多条记录使用相同的时间戳,于是就可能出现相互覆盖以致这些数据行无法全部被正确保存。其原因在于,NOW 函数在执行中会被解析为所在 SQL 语句的实际执行时间,出现在同一语句中的多个 NOW 标记也就会被替换为完全相同的时间戳取值。

 --资料来源:文档 - 涛思数据 | TDengine

   TDengine是单个数据一张表,可以通过超级表管理。在底层逻辑上,还是仅有子表名和ts时戳1个主键。Iot数据在同一时刻数据也仅会变化一次,正常使用是没有问题。

    但最近在使用TDengine记录日志时,就遇到一个场景,我对Iot来的报文进行日志记录,每个设备一张表,以服务端处理时间做ts主键。后来根据计数器核对数据时发现数据丢失严重,忽然想起之前看过的涛思官网上看到的上述资料,知道了原因所在。找对症处理起来就很容易了。

     这个服务采用JAVA编写,先定义一个锁用于支持并发,定义一个变量记录上次的时间,时间单位是ms。在写入时不使用now直接插入,而是采用时间值。如果当前时间与上次的相同或小,就使用上次时间+1.。

import java.time.Instant;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

    private static Lock lock = new ReentrantLock();
    private long lastStatTs = 0;

。。。
    //处理高并发下的ts重复问题
    long insMilli = Instant.now().toEpochMilli();
    lock.lock();
    if ( lastStatTs < insMilli )
    {
       lastStatTs = insMilli;
    }else {
       lastStatTs ++;
    }
    //示例Sql,插入使用lastStatTs
    INSERT INTO d1001 VALUES (lastStatTs, 10.2, 219, 0.32);    

   使用上面的方法,可以解决数据有高并发,但数据密度有限的情况。

   如果涉及超级表和Iot数据保存,建议在数据源带时戳,设计好数据模型,避免在服务端处理数据时戳造成的数据重复问题。

你可能感兴趣的:(IoT,编程,涛思数据,tdengine,java)