1.
...
设计概述
1.1.
...
目标场景
...
在用户密切关心序列最新值的场景中,Last 查询(最新点查询)的性能很重要。
...
因此设计最新点缓存(lastCache),在内存中缓存序列的最新值、或在磁盘上以一种更高效的格式(ID表)存储每条序列的最新点。
1.2.
...
概要设计
insertPlan执行完后updateLastCache- 为了对每一条时间序列都缓存最新点,因此在元数据树上开辟lastCache字段。
last查询,先从缓存中查找,若miss则从文件获取数据后updateLastCache- 代码结构
delete数据时,根据删除数据的起始时间清空lastCache- 为了提升功能代码的内聚性,通过设计ILastCacheContainer接口,将LastCache操作与MNode解耦,由LasCacheContainer实现ILastCacheContainer接口,封装lastCache数据同时提供简单的lastCacheValue操作。
- upload Tsfile时,由于数据更新,lastCache可能失效,故清空
1.3. lastCache操作执行过程
- getLastCache:首先通过调用getNodeByPath,获取指定路径/序列对应的 MeasurementMNode,template对应的序列会封装一个临时节点对象,调用MeasurementMNode的get接口
- updateLastCache:与getLastCache类似
- resetCache:storageGroupProccessor通过device获取子节点,调用子节点的reset接口
2. 0.13版本lastCache功能实现
2.1. 适配物理量模板Template
Template的lastCache失败原因
获取template中序列对应的measurementMNode时,仅返回临时变量,对临时MeasurementMNode中lastCache的操作并未保存回MTree。
适配方案
由于Template由EntityMNode进行使用,因此在EntityMNode中增加Map<String, ILastCacheContainer>字段,用于存储template所表示的时间序列的lastCache。
对MeasurementMNode中的lastCache进行操作时,先判断该节点是否是为了template而创建的临时节点,如果是,则先拿到entityMNode中的lastCache引用,然后再进行操作。
2.2. 适配多元时间序列
多元时间序列的lastCache失败原因
- MeasurementMNode中简单的TimeValuePair无法满足多元分量的lastCache的存储。
- LastQueryPlan的执行过程中,path被转化为vectorPartiaPath之后,仅到多元序列层,未基于分量路径subsensorPath进行lastCache查找
- insertPlan执行过程中,对于aligned plan不进行lastCache的更新
适配方案
- 建立VectorLastCacheValue,存储多元时间序列的lastCache;由于目前last查找是查找最新的不为空值的时间点,故不同分量的LastCache时间可能不同,需要存储多个timestamp和 TsPrimitiveValue。
- 修改LastQueryExecutor中seriesPath的使用,使其应用到subsensor层即分量对应的路径。
- 实现insertPlan过程的vector lastCache更新。
2.3. LastCache方案详情
2.3.1. 设计思路
- 为了提升功能代码的内聚性,通过设计ILastCacheContainer接口,将LastCache操作与MNode解耦,由LasCacheContainer实现ILastCacheContainer接口,并封装lastCache数据,同时提供简单的lastCacheValue操作。
- 新建LastCacheManager,将MManager中与lastCache相关的操作代码尽可能迁移至 LastCacheManager,MManager中仅保留必要的mtree调用以及mnode获取操作。
- EntityMNode中增加Map<String, ILastCacheContainer>字段,用于存储template中序列的lastCache;MeasurementMNode中将原来的TimeValuePair替换为ILastCacheContainer,用于存储普通序列的lastCache。
2.3.2. 类设计
- 新建LastCacheManager,将MManager中与lastCache相关的操作代码尽可能迁移至 LastCacheManager,MManager中仅保留必要的mtree调用以及mnode获取操作。
- 适配物理量模板:
- 由于Template由EntityMNode进行使用,因此在EntityMNode中增加Map<String, ILastCacheContainer>字段,用于存储template所表示的时间序列的lastCache。
- EntityMNode中存储模板对应序列的lastCache,MeasurementMNode中存储普通序列的lastCache。
2. 类设计
Image Added
Image Removed
类名 | 职责 |
StorageGroupProccessor | 与MManager进行交互,在数据插入、数据删除以及上传新tsfile的时候清空对应序列的lastCache |
LastQueryExecutor | Last查询执行类,调用MManager进行lastCache操作 |
MManager | - 对IoTDB的其他模块提供lastCache的操作接口
- 为LastCacheManager提供node查找功能
|
IEntityMNode与EntityMNode | 实体节点,存储由物理量模板所表示的时间序列的lastCache,即Map<String, ILastCacheContainer> |
IMeasurementMNode与MeasurementMNode | 物理量节点,手动创建时间序列时产生,存储其表示的时间序列的lastCache |
LastCacheManager | 封装所有的lastCache处理逻辑,并向mmanager提供lastCache操作接口 |
ILastCacheContainer | 最新点缓存项接口,声明最新点缓存的操作接口最新点缓存项接口,声明最新点缓存的操作接口,该接口未来可向多条value缓存扩展 |
LastCacheContainer | 实现ILastCacheContainer,定义对于一个最新点缓存值的基本操作 |
ILastCacheValue | 最新点缓存值接口,声明 |
UnaryLastCacheValue | 一元序列的最新点缓存值 |
VectorLastCacheValue | 多元序列的最新点缓存值,存储各分量对应的最新点的时间戳与数值 |
...
MManager对外接口
功能 | 接口 | 解释 |
---|
更新lastCache | public void updateLastCache( PartialPath seriesPath, TimeValuePair timeValuePair, boolean highPriorityUpdate, Long latestFlushedTime) | 接收seriesPath作为参数, 用于更新序列的lastCache, 需传入序列全路径。 |
public void updateLastCache( IMeasurementMNode node, TimeValuePair timeValuePair, boolean highPriorityUpdate, Long latestFlushedTime) | 接收单个MeasurementMNode作为参数, 用于更新序列的lastCache |
获取lastCache | public TimeValuePair getLastCache(PartialPath seriesPath) | 接收seriesPath作为参数, 用于获取序列的lastCache, 需传入序列的全路径 |
public TimeValuePair getLastCache(IMeasurementMNode node) | 接收单个MeasurementMNode作为参数, 用于获取序列的lastCache |
删除lastCache | public void resetLastCache(PartialPath seriesPath) | 接收seriesPath作为参数, 用于清除序列的lastCache, 需传入序列的全路径 |
public void deleteLastCacheByDevice(PartialPath deviceId) | 用于清除一个device下所有序列的lastCache |
public void deleteLastCacheByDevice( PartialPath deviceId, PartialPath originalPath, long startTime, long endTime) | 由于清除一个device下匹配originalPath的、且last值在startTime和endTime之间的所有序列的lastCache |
3. 调用场景及执行过程
3.1. last cache查询
last cache查询主要在Last Query的执行过程中,由LastQueryExecutor中的LastCacheAccessor进行调用。
- LastCacheAccessor通过调用MManager.getNodeByPath(PartialPath path)获取序列对应的MeasurementMNode
- 如果是普通序列,则正常返回MeasurementMNode
- 如果是template表示的序列,则将对应的序列schema与封装为临时的MeasurementMNode返回
- LastCacheAccessor调用MManager.getLastCache
- 若1中的操作成功,则可传入node,避免MManager对measurementMNode的二次查找。
- 若1中节点获取失败,则尝试仅基于path查找lastCache结果,此时MManager会基于path进行MeasurementMNode查找
- MManager调用LastCacheMManager的getLastCache接口
- 判断是否为template表示的序列,即判断传入的measurementMNode的parent EntityMNode是否有对应的子节点,若无则从EntityMNode中获取到LastCacheContainer并赋予该measurementMNode
- 如果是普通序列,获取measurementMNode中的lastCacheContainer后获取其持有的lastCacheValue
2中情况的一个典型场景为分布式中,node的获取不会返回本地缓存的remote measurementMNode,但是lastCache查询可以先走remote measurementMNode中进行查询。
3.2. last cache更新
3.2.1. Last Query执行过程中的last cache更新
last查询过程中,若cache miss,则会从文件中读取last value,并且将该值进行缓存,此时LastCacheAccesso将调用MManager的updateLastCache接口。
与getLastCache接口类似,updateLastCache接口也可以path和node双参数传入。
- 如果LastCacheAccessor先前已成功获取node,则将node传入,MManager避免node的二次查找
- LastCacheAccessor先前未获取到node,则基于path更新lastCache,MManager将基于path查找对应node
- MManager调用LastCacheManager的updateLastCache接口,不同类型序列的处理逻辑与3.1中3的逻辑大致相同
3.2.2. insertPlan执行过程中的last cache更新
insertPlan执行过程中,插入的数据的最新点需缓存,由StorageGroupProcessor调用MManager的updateLastCache接口。
为了解决insert和last query的并发更新,updateLastCache中设置priority参数,insert的last cache更新优先级高于last query。
3.3. last cache 清除
3.3.1. delete执行过程中的last cache清除
StorageGroupProcessor在执行delete的过程中,会基于用户输入的originPath以device为单位进行删除操作,originPath是一个可以包含通配符*的路径,需筛选device下与其相匹配的时间序列。
lastCache的删除过程中需根据删除数据的起始时间进行判断是否要清空缓存。
因此MManager提供deleteLastCacheByDevice(PartialPath deviceId, PartialPath originalPath, long startTime, long endTime)接口,MManager获取节点后,具体清除逻辑由LastCacheManager进行执行。
EntityMNode中template的LastCacheContainer与MeasurementMNode的LastCacheContainer均需检查是否需要清空。
3.3.2. upload tsfile执行过程中的last cache清除
upload tsfile后由于引入了新数据,需将对应序列的last cache清空,此过程也是以device为单位进行执行。
MManager提供deleteLastCacheByDevice(PartialPath deviceId)接口,具体过程与3.3.1类似。
4. LastCache扩展方向
- LastCache缓存多条数据,LastCacheContainer向BatchedLastCacheContainer扩展
- 底层实现重写,如lastCache存储Memtable中最新的批量数据