汇报block产生大量IO问题

问题背景

TFS里每块磁盘的存储空间被划分为多个block(通常64M),每个block里存储多个小文件,为了快速定位文件在block内部的位置,每个block对应一个index文件,index文件包含一个描述block元信息的header,然后是每个文件在block内部的位置信息,以哈希表的方式组织。

enter image description here

index文件通常数十KB,直接mmap到内存,内存完全交给操作系统来管理,比较活跃的block,其index的访问通常直接page cache命中,不用访问磁盘;当内存不足时,index对应的page cache有可能被操作系统换出至磁盘,导致index的访问不能从page cache未命中,此时则会从磁盘读取index数据。

根据TFS里文件数据访问的特性,新写入的数据被访问的可能性更大,而老的数据因为访问较少,其所在block的index通常会从内存换出,Linux本身的page cache策略与TFS的文件访问特性能很好的配合,但TFS另一个周期性任务却受page cache管理策略的影响。

TFS里的dataserver(DS)每天会给nameserver(NS)汇报一次所管理的block信息,以便让NS尽快修正不一致的元数据。比如某个block原来在A,B两台机器上,但由于负载不均衡,NS发起迁移任务将该从A迁移到C,假设由于网络原因,迁移耗时超出预期,导致NS认为迁移任务失败了,但实际上该block已经在C上产生一个副本,这时NS上认为该block有A,B两个副本,但实际上它有A,B,C三个副本,这种不一致会导致该block一直有一个多余的副本,而DS周期性(每天)汇报就是为了解决这种不一致问题。

DS汇报block时,会从所有的block的index文件里读取header信息,一并发给NS,在读取header时,如果index没有从page cache命中,则会产生从磁盘读取。一个4T盘,大概有6w个block,每个block一个index文件,当因机器内存不足导致大量index被换出内存时,汇报过程会带来大量的磁盘IO,对正常的文件读写服务影响很大,导致部分请求超时。

解决方案

针对这个问题,想到的解决方案有两种,一种是将index的header所在页面mlock到内存,使其常驻内存不被换出;一种是在内存里维护一份header的副本,并保持与磁盘副本同步更新。

mlock内存页面

  1. mlock以内存页为单位,4T盘mlock所有的页面需要6W * 4K = 240M内存,每台机器12块盘,总共需要约2.4G内存。
  2. linux下锁定内存的大小是有限制的(ulimit -l),如果使用mlock,则针对每台机器都需调整限制,增加了运维成本。

维护header的内存副本

  1. header的大小约200bytes,4T盘,6w个header,占用内存,6W * 0.2K = 12M
  2. 在header更新的时候同时更新内存副本,增加了一定的内存拷贝开销,场景包括创建block、写文件、删除文件、复制block等,而TFS总体读多写手(约30:1),更新header并不是经常性事件。

从占用内存、对系统的影响、以及运维度综合考虑,决定通过在内存里维护header的副本来解决汇报IO问题,DS在汇报时,直接读取每个block的header在内存里的副本,不产生任何磁盘IO。

ref:
2014-09-28
blog.yunnotes.net

0 回复
需要 登录 后方可回复, 如果你还没有账号你可以 注册 一个帐号。