@HUST张友东 work@taobao zyd_com@126.com
分类: 服务器与存储
2012-04-20 12:49:41
TFS数据服务器(DS)通过在物理块的头部存放一个BlockPrefix结构来记录逻辑块与物理块的对应关系,在DS时,会读取每一个已经使用的block,并读取block头部的信息,汇报给NS,NS通过这些信息建立逻辑块到DS的映射关系。最初,TFS使用300G的小盘,按照每个主块64M,每个扩展块2M计算,物理块的总数接近1500个,即使这些块全部使用全部使用了(正常状态下扩展块的利用率不会太高),加载这些物理块也不到30s,这个时间是可以忍受的,但目前TFS多使用2T的盘,物理块总数会在7w左右,整个加载时间会随着块的个数线性扩大,当块全部使用时,加载过程应该会到十几分钟,对于服务器来说这是无法忍受的,必须对启动过程进行优化。
DS启动过程主要耗时在于BlockFileManager::bootstrap的过程,该过程执行如下任务:
1. 加载超级块 load_super_blk
2. 根据超级块信息加载数据块 load_block_file (主要时间耗在这里)
load_block_file过程中,对于每个逻辑块,要先读取其对应物理块(一个主块,多个扩展块)的头部信息,建立逻辑块和物理块的对应关系,然后再mmap对应的index信息。
逻辑块的链式加载是根据block头部的BlockPrefix进行的,BlockPrefix结构如下:
struct BlockPrefix { uint32_t logic_blockid_; // 该物理块对应的逻辑块号 uint32_t prev_physic_blockid_; // 下一个物理块的块号 uint32_t next_physic_blockid_; // 上一个物理块的块号,为0代表最后一个 };Index的加载包含open、mmap操作,并读取映射内存区头部的BlockInfo信息用于汇报给ns。
对比测试,物理块的加载和index的加载谁更耗时?
测试环境:2T的盘接近满,DS上逻辑块数22134个
从上面的测试可以看出,时间主要消耗在物理块的加载上,因物理块的空间是预先分配的,不断的读取各个block头部会引发磁盘随机读操作。
优化方案
将分散的BlockPrefix集中存储在一个文件中(因物理块数是确定的,文件大小也就确定了,文件的空间可预先分配好),在加载过程中只集中读取该文件来建立逻辑块与物理块的对应关系,从而减少大量的随机读。
Block的头部加载和更新通过接口load_block_prefix、dump_block_prefix完成,使用新的方案,需要修改这两个接口的实现,由从block头部读取换成从单独的文件读取,如果发现单独没有存储BlockPrefix的文件,则仍使用原来的方案启动。
配套工具改动
优化效果
采用集中存储BlockPrefix方案,分别对已运行的DS和使用新方案创建的DS两种情况进行了测试,DS启动时间在10s以内,且DS能正常的完成读写服务请求。