java代码批量插入一批数据到disk表,去influxdb上看只有一条数据,到底问题出在哪?
第一步:
了解influxdb的机制,它是基于时间的时序性数据库,每一条记录都会默认给一个时间标识,这个时间标识是不可以重复的,如果重复,后面的将覆盖前面的,根据机制很快就定位到了问题的主要原因。
第二步
我插入一批数据,为什么会插入时间相同呢?直接上代码
for(BdmpTenantUsage bdmpTenantUsage :bdmpTenantUsages ){
String tenantName = bdmpTenantUsage.getTenantName();
if(StringUtils.isNotBlank(tenantName)) {
if( bdmpTenantUsage.getCpuUsageRate() )
Point cpu_point = Point.measurement("disk")
.time(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
.addField("unit_id", "cpu_usage")
.addField("value", bdmpTenantUsage.getCpuUsageRate())
.addField("tenant_name", tenantName)
.build();
Point memory_point = Point.measurement("disk")
.time(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
.addField("unit_id", "memory_usage")
.addField("value", bdmpTenantUsage.getMemoryUsageRate())
.addField("tenant_name", tenantName)
.build();
Point storage_point = Point.measurement("disk")
.time(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
.addField("unit_id", "storage_usage")
.addField("value", bdmpTenantUsage.getStorageUsageRate())
.addField("tenant_name", tenantName)
.build();
batchPoints.point(cpu_point).point(memory_point).point(storage_point);
}
}
influxDB.write(batchPoints);
直接看时间的代码: .time(System.currentTimeMillis(), TimeUnit.MILLISECONDS);
代码执行的效率比较高且数据量小(我的数据仅有100个)的情况下,System.currentTimeMillis()获取的时间戳可能会相同,导致我这一批数据的时间都是相同的,所有后一个值覆盖了前面的值,最终influxdb表里只能查询到一条数据。
第三步
解决方案:
既然知道是时间的问题,那就从时间入手。我在解决的时候并没有思路这么清晰,中间走了个弯路。
我起先任务修改插入时间的单位就行了。直接将TimeUnit.MILLISECONDS修改成TimeUnit.MICROSECONDS(也就是将毫秒改成微秒),然后运行代码来了另一个错误:
partial write: points beyond retention policy dropped=140
这个是什么意思呢 what?
插入的数据点中有时间戳在此范围之外的,就会导致这个错误。
为什么呢 why?
System.currentTimeMillis()返回的是毫秒,后面要求的单位是微秒,两者不对应造成的错误。
下面附上两段代码:
// 获取毫秒, 网上百度都有
public static Long getmicTime() {
Long cutime = System.currentTimeMillis() * 1000; // 微秒
Long nanoTime = System.nanoTime(); // 纳秒
return cutime + (nanoTime - nanoTime / 1000000 * 1000000) / 1000;
}
InfluxdbConnection conn = InfluxdbConnection.builder()
.openurl(openurl)
.username(username)
.password(password)
.database(database)
.build();
InfluxDB influxDB = InfluxdbConnectionUtils.influxDBBuild(conn);
String rpName = "aRetentionPolicy";
BatchPoints batchPoints = BatchPoints
.database(database)
.tag("aync", "true")
.retentionPolicy(rpName)
.consistency(InfluxDB.ConsistencyLevel.ALL)
.build();
for(BdmpTenantUsage bdmpTenantUsage :bdmpTenantUsages ){
String tenantName = bdmpTenantUsage.getTenantName();
if(StringUtils.isNotBlank(tenantName)) {
Point cpu_point = null;
Point memory_point = null;
Point storage_point = null;
String cpuUsageRate = bdmpTenantUsage.getCpuUsageRate();
String memoryUsageRate = bdmpTenantUsage.getMemoryUsageRate();
String storageUsageRate = bdmpTenantUsage.getStorageUsageRate();
if(StringUtils.isNotBlank(cpuUsageRate)) {
cpu_point = Point.measurement("disk")
.time(DateUtils.getmicTime(), TimeUnit.MICROSECONDS)
.addField("unit_id", "cpu_usage")
.addField("value", cpuUsageRate)
.addField("tenant_name", tenantName)
.build();
batchPoints.point(cpu_point);
}
if(StringUtils.isNotBlank(memoryUsageRate)) {
memory_point = Point.measurement("disk")
.time(DateUtils.getmicTime(), TimeUnit.MICROSECONDS)
.addField("unit_id", "memory_usage")
.addField("value", bdmpTenantUsage.getMemoryUsageRate())
.addField("tenant_name", tenantName)
.build();
batchPoints.point(memory_point);
}
if(StringUtils.isNotBlank(storageUsageRate)) {
storage_point = Point.measurement("disk")
.time(DateUtils.getmicTime(), TimeUnit.MICROSECONDS)
.addField("unit_id", "storage_usage")
.addField("value", bdmpTenantUsage.getStorageUsageRate())
.addField("tenant_name", tenantName)
.build();
batchPoints.point(storage_point);
}
}
}
influxDB.write(batchPoints);