Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  1. 一个insertPlan写入完成后,检查该TSP的 workingMemtable 的 shouldFlush 字段,如果为 true,再检查是否TsFile大小超过阈值,如果超过,flush memtable后将文件封口。
  2. TsFile关闭完成后,清空该TSPInfo,重置对应的 SGInfo 状态,并向SystemInfo报告重置后SGInfo
  3. 如果此时SystemInfo 为reject状态 且 `SystemInfo中统计的总内存 < 总写入内存 * reject_proportion`,将SystemInfo 置于正常状态
  4. 如果`SystemInfo 总内存 >= 总写入内存 * 50%`,触发即时flush

 

MTree内存控制:

注册时间序列时,如果总时间序列个数*300 estimate_series_size > 总内存*0.1,此时拒绝注册,抛出异常。write_read_schema_free_memory_proportion:schema,此时拒绝注册,抛出异常。



细节:关于Array Pool中分类型的数组如何管理?

...

TsFile封口时,更新ChunkMetadata和Resource的内存统计并上报给System

Historical Resource 设计

采用二级索引的方式来降低TsFileResource常驻内存的数量,进而控制内存使用。

rootFile: 记录是<device, [starttime, endTime, IndexFile]>,是TsFileResource的根索引,常驻内存

IndexFile:记录是<device, [starttime, endTime, TsFileRecource]>, 是TsFileResource的中间索引,固定大小,按需load进内存

TsFileResource:记录是<device, starttime, endTime>, 是TsFile的索引,按需load进内存

写入

TsFile关闭时,unsealed_resource刷入磁盘;维护IndexFile,将涉及的各device的tsfile resource都进行记录。

如果IndexFile文件大于阈值(1GB)了,就进行关闭持久化到磁盘上,并开启一个新的IndexFile用于记录下一批TsFileResource中间索引。IndexFile关闭时,往rootFile里继续写一批记录,将涉及的各device的 index file都进行记录。

细节:rootFile也过大怎么办?

解法:多级索引(缺点,一次查询过多次访问磁盘);或者在rootFile中忽略一些device(缺点是这些设备的查询需要逐个去扫描indexFile)

...

估算下一个rootFile可以索引多少个TsFileResource。

假设:

1个storage group,每个设备100个测点,每个storage group 51200个设备, 也就是5.12e6个测点

内存128GB

Tsfile 512MB

IndexFile是1GB

每条ResourceIndex 100B,一个IndexFile是1GB,可以记录1GB/100B=10240000条记录,也就是200个TsFileResource。

每个rootFile在一个IndexFile关闭时会记录一下,也是51200*100B=5.12MB

 

也就是200个TsFileResource会产1GB的IndexFile和5.12MB的rootFile

 

100T的磁盘空间,有100T/512MB=100000个TsFile,需要100000/200 * 1GB = 500GB IndexFile,100000/200*5.12MB= 2.56GB内存

 

 

假设一个storage group A个设备,一个设备D个测点, 总共就是A * D个测点

假设每次TsFile刷写会造成所有设备的索引更新,就会产生A * 100B 的IndexFile记录

 

一个IndexFile假设是 C GB, 那一个IndexFile能支持 C * 1000,000,000 / A * 100 = C * 10,000,000/A 个TsFile的刷写

 

IndexFile关闭时,也会在RootFile里记录下A * 100B的rootFile记录

 

也就是C * 10,000,000/A 个TsFile的刷写,会有C GB的IndexFile产生, 还有A * 100B的rootFile记录

 

假设整个数据库有S个 Storage group,那么常驻内存的就是 S * (rootfile + C GB)

 

A 平均一个storage group 设备数

D 平均一个设备测点数

C IndexFile文件大小,单位是GB

512MB TsFile大小

 

rootFile = C * 10,000,000/A * 100B

IndexFile= C GB

磁盘空间= C * 10,000,000/A * 512MB

测点=A * D

 

 

该估算有个问题就是对于TsFileName长度可以进行优化,可以只消耗Tsfile个数的TsFilename长度内存占用,而不是device * [starttime, endTime] * tsFile个数来估算,因此其内存占用估算放大了很多倍。

 

这个优化的前提是java的string 常量池,可以保证多个string公用一个字符串常量。

 

因此,限制一个StorageGroup的设备数是可以做到只使用(2.56GB+1GB)/128GB~ 3%的内存索引100TB的磁盘空间。

读取流程

  1. 查找常驻内存的rootFile,找到对应的device的记录,根据startTime和endTime,找到对应的IndexFile。
  2. load IndexFile进内存,找到对应的device的记录,根据startTime和endTime,找到对应的TsFile。
  3. load TsFile在内存中构造TsFileResource

merge流程

TsFile会定期的跟乱序文件进行合并,因此其名字和元数据也会进行更新。

对于新生成的TsFile,也需要往IndexFile里写入记录即<device, ResourceIndexs>, 但是这个会造成有多个indexFile里某条device的记录区间有重叠的情况。

例如有IndexFile1记录的device, 10, 200, Tsfile1,  merge后,新的indexFile2记录device, 10,400, tsFile2。

这两条记录都会在rootFile里进行记录,查询的时候需要读取两个IndexFile,但是IndexFile1里的TsFile1找不到了,那就不再查找。只找IndexFile2里的TsFile2.

 

这里会多读一次文件,为了减少这种无效的索引干扰,可以在merge 数据结束后进行一下相关IndexFile的合并操作,尽量保证一个device的一个时间区间在一个IndexFile里。

cache优化

...


文档原链接: https://shimo.im/docs/CWxXTDhvkRrHvXPx