You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 6 Next »

锁的种类

insertLock in StorageGroupProcessor

用以保护StorageGroupProcessor中的内存结构,如当前的workingTsFileProcessor、latestTimeForEachDevice、partitionLatestFlushedTimeForEachDevice、newlyFlushedPartitionLatestFlushedTimeForEachDevice、globalLatestFlushedTimeForEachDevice、partitionMaxFileVersions等等

compactionMergeLock in TsFileManagement

用以保护TsFileManagement中管理的顺序和乱序的TsFileResource的List,所有对TsFileResource的List的写操作(比如写入时,创建新的TsFileResource,compact时删除旧的TsFileResource,并产生新的TsFileResource)需要获得其写锁,所有对TsFileResource的List的读操作(如查询时获得满足此次查询条件的所有TsFileResource)需要获得其读锁

resourceListLock in TsFileResourceManager

用以保护TsFileResourceManager中管理的顺序和乱序的TsFileResource的双向链表,所有对TsFileResource的List的写操作(比如写入时,创建新的TsFileResource,compact时删除旧的TsFileResource,并产生新的TsFileResource)需要获得其写锁,所有对TsFileResource的List的读操作(如查询时获得满足此次查询条件的所有TsFileResource)需要获得其读锁

tsFileLock in TsFileResource

用以保证此TsFileResource对应的单个Tsfile的一致性,删除tsfile需要获得其写锁,查询期间,涉及到的所有tsfile文件,需要一直持有他们的读锁

以上三个锁的获取顺序

因为常常在某一操作流程中,为了保证正确性,需要获得这三个锁中的两个或者全部,所以为了避免产生死锁,所以以上三个锁的获得需要有一定的顺序约束,现在约定俗成的顺序是:

insertLock → compactionMergeLock → tsFileLock

查询获取和释放锁的流程

首先调用StorageEngine.mergeLock,根据每个查询涉及的序列,获得这些序列所属的所有StorageGroupProcessor,按照StorageGroupProcessor的name的字母序排序后,依次对每个StorageGroupProcessor进行加锁,这个加锁过程先获取insertLock的读锁,再获得compactionMergeLock的读锁。


然后,对每个涉及的序列调用QueryResourceManager.getInstance().getQueryDataSource,获得该序列满足查询条件的所有的TsFileResource,并对所有的TsFileResource调用QueryFileManager.

addUsedFilesForQuery,为其加上tsFileLock的读锁

调用StorageEngine.mergeUnlock,释放第一步中获得的所有StorageGroupProcessor的insertLock和compactionMergeLock

在查询处理期间,持有所有文件的tsFileLock的读锁,直到查询结束,释放tsFileLock的读锁。

写入获取和释放锁的流程


写入获取锁的流程较为简单,在StorageGroupProcessor中,每一个insert接口都会直接获取该SGP的insert lock的写锁,直至写入完成,返回StorageEngine后再释放写锁,具体写入接口如下:

public void insert(InsertRowPlan insertRowPlan)

public void insert(InsertRowsOfOneDevicePlan insertRowsOfOneDevicePlan)

public void insertTablet(InsertTabletPlan insertTabletPlan)

另外一个获取锁的地方是flush,当内存控制需要将某个tsfile刷入磁盘时,会先拿tsFileLock的写锁,再进行刷盘,具体刷盘接口如下:

public void asyncFlush()

public void asyncClose() 

写入过程中还会拿resourceListLock

resourceListLock.writeLock()

修改resourceList

resourceListLock.writeUnlock()


合并获取和释放锁的流程

合并对锁的获取主要分为两部分:

外部获取及修改TsFileResource列表:

都是针对于compactionMergeLock的锁

所有对TsFileResource的List的读操作(如查询时获得满足此次查询条件的所有TsFileResource)需要获得其读锁

所有对TsFileResource的List的写操作(比如写入时,创建新的TsFileResource)需要获得其写锁

即,对于每一个文件列表相关操作,其锁的获取和释放格式为


resourceListLock.readLock()/resourceListLock.writeLock();
// 对列表读取或更改操作
resourceListLock.readUnlock()/resourceListLock.writeUnlock();


提交合并任务:

1、resourceListLock.readLock()

2、提交合并任务

3、resourceListLock.readUnlock()

合并完对文件列表和实际文件进行删除和新增:

1、resourceListLock.writeLock(long timeout)

2、然后进行文件列表的旧文件删除和新文件的增加

3、resourceListLock.writeUnlock()

4、循环要删除的每一个TsFile文件,对于每一个TsFile文件进行如下操作:

  1、获取TsFileResource的tsFileLock写锁

  2、删除文件

  3、释放TsFileResource的tsFileLock写锁


删除获取和释放锁的流程

在StorageGroupProcessor中,每一个删除接口都会直接获取该SGP的insert lock的写锁,直至删除完成、或者捕获异常后释放写锁。

deleteFolder(String systemDir) // 删除data/system下的sg文件夹

delete(PartialPath path, long startTime, long endTime, long planIndex) // 删除时间序列数据

syncDeleteDataFiles() // 删除这个sg里的所有数据文件

removePartitions(TimePartitionFilter filter) //删除时间分区

删除时间分区还会拿resourceListLock:

resourceListLock.writeLock()

等待此分区的所有合并任务结束

delete 此分区所有文件

resourceListLock.writeUnlock()


  • No labels