背景简介


某用户在一台16GB内存的机器上使用IoTDB 0.11.4-SNAPSHOT版本管理2000条时间序列,采样频率在1hz~50hz不等。用户将这2000条序列分到了40个存储组内。写入时会有一定的乱序数据。JVM内存设置为8GB。



之前手动修改过的配置参数如下:

write_read_schema_free_memory_proportion=2:5:1:2

storage_group_report_threshold=4777216

avg_series_point_number_threshold=40000

wal_buffer_size=16777216

seq_file_num_in_each_level=4

seq_level_num=4

在上述情况下,用户发现写入会经常出现reject的情况。

排查过程


检查server日志发现,刷盘时每个memtable的大小非常小,不符合预期。


按照计算,如果memtable由内存控制模块控制大小,每个memtable应该有8GB * 0.2 / 40 * 0.4 = 16MB。

猜想是内存控制模块统计的内存对比实际memtable使用量过多了,由此导致memtable只用了很小一部分内存就触发了磁盘。


内存控制目前统计的内存模块如下:

  1. memtable大小
  2. 未关闭的TsFileResource内存
  3. 未关闭的ChunkMetadata内存
  4. wal内存(每个未关闭文件16MB)


于是,使用jprofiler进行了具体内存使用量的排查。


jprofiler显示TsFileResource占用内存较多。原因也很清楚,是用户在该场景下生成的文件个数太多。

但是这里的文件均代表已关闭的文件,已关闭的resource虽然会占用内存,但是不会统计在内存控制模块中,不会影响写入,造成reject。 因此问题不是该原因造成的。

由于tsfile_size_threshold=1,所以也不会有过多的未关闭TsFileResource和ChunkMetadata的影响。

如果reject与已关闭文件无关,那就只剩上面内存统计列表里的最后一项wal了。


WAL在内存控制里为每开一个TSP就统计16MB。在该用户的使用场景下,每个memtable的flush阈值为8GB * 0.2 * 0.4 / 40 / 2 = 8MB。相当于刚开一个TSP时就已经超过了flush阈值,写入一个点后就触发了刷盘,符合用户反馈的现象。

解决方法


调整wal_buffer_size=1MB,减小WAL对写入内存控制的影响。

经调整,memtable大小如下,符合正常预期。


总结

  1. 当在总内存较小,存储组过多的情况下,需要注意wal的大小会影响memtable的大小,需要做相应调整。
  2. 考虑在内存小的情况下限制用户创建过多的存储组


  • No labels