...
insertLock → compactionMergeLock → tsFileLock
查询获取和释放锁的流程
首先调用StorageEngine.mergeLock,根据每个查询涉及的序列,获得这些序列所属的所有StorageGroupProcessor,按照StorageGroupProcessor的name的字母序排序后,依次对每个StorageGroupProcessor进行加锁,这个加锁过程先获取insertLock的读锁,再获得compactionMergeLock的读锁。
然后,对每个涉及的序列调用QueryResourceManager.getInstance().getQueryDataSource,获得该序列满足查询条件的所有的TsFileResource,并对所有的TsFileResource调用QueryFileManager.
...
- 在各种查询 Executor 的初始化方法中
- 调用StorageEngine.mergeLock
- 根据每个查询涉及的序列,获得这些序列所属的所有StorageGroupProcessor,按照StorageGroupProcessor的name的字母序排序
- 对于每个查询涉及的 StorageGroupProcessor
- 对 insertLock 加读锁,对 compactionMergeLock 加读锁
- 对每个涉及的序列所在的 StorageGroupProsessor
- 对 insertLock 加读锁,对 compactionMergeLock 加读锁
- 选择待查的 TsFileResource 列表
- 对于待查的每个 TsFileResource
- 对 TsFileLock 加读锁
- 释放 insertLock 和 compactionMergeLock 的读锁
- 调用StorageEngine.mergeUnlock,对每个涉及的序列所在的 StorageGroupProsessor
- 释放 insertLock 和 compactionMergeLock 的读锁
- 直到查询结束,释放所有 TsFileLock 的读锁
写入获取和释放锁的流程
写入获取锁的流程较为简单,在StorageGroupProcessor中,每一个insert接口都会直接获取该SGP的insert lock的写锁,直至写入完成,返回StorageEngine后再释放写锁,具体写入接口如下:
...
public void asyncClose()
写入过程中还会拿resourceListLock
...
- 写入过程中,新建一个文件,并把 TsFileResource 加到 list 时
- compactionMergeLock.writeLock()
- 修改resourceList
...
- compactionMergeLock.writeUnlock()
合并获取和释放锁的流程
合并对锁的获取主要分为两部分:
外部获取及修改TsFileResource列表:
都是针对于compactionMergeLock的锁
所有对TsFileResource的List的读操作(如查询时获得满足此次查询条件的所有TsFileResource)需要获得其读锁
所有对TsFileResource的List的写操作(比如写入时,创建新的TsFileResource)需要获得其写锁
即,对于每一个文件列表相关操作,其锁的获取和释放格式为
...
- 选择文件时
- compactionMergeLock.readLock()
- 拷贝 resourceList
- compactionMergeLock.readUnlock()
- 合并文件结束时
- compactionMergeLock.writeLock()
...
- 修改 resourceList,移除要删除的 TsFileResource
- compactionMergeLock.readUnlock()
...
- 对于每个待删除的 TsFileResource
- 拿 TsFileLock 的写锁
- 删文件
- 释放 TsFileLock 的写锁
- 对于每个待删除的 TsFileResource
提交合并任务:
1、resourceListLock.readLock()
...
3、释放TsFileResource的tsFileLock写锁
...
数据删除操作
在StorageGroupProcessor中,每一个删除接口都会直接获取该SGP的insert lock的写锁,直至删除完成、或者捕获异常后释放写锁。
...