从tfs优化看分布式存储系统

来源:互联网 发布:linux ant安装配置 编辑:程序博客网 时间:2024/04/29 20:01

        因为TFS是采用星型的设计架构的,通过一个Nameserver和多个Dataserver来对外进行服务,并且Nameserver中的元数据均是存放在内存中,因此如何减少Nameserver中内存的占用量,以及如何提高Nameserver的服务能力,减少单点的压力便成了TFS进行优化的一个重要方向。

       对于读文件操作,客户端首先将TFS文件名进行解析(其实这一步也是为了减轻Ns的压力,将文件名的解析工作由客户端来做),拿到BlockidFileid,通过BlockidNs进行请求,拿到该Block对应的Ds列表,然后再和Ds进行交互读文件。事实上,针对同一个Block进行多次读操作,如果有缓存存在,那么就不必要每次在读真正数据之前都和Ns进行交互了,这样就可以减轻Ns很大一部分压力了。所以,我们针对这一方面的优化做了本地缓存和远程缓存(均设置了开关),远程缓存采用的是淘宝另一个KV分布式存储产品Tair。因此,针对存储产品而言,前端增加缓存往往能带来一定的优化,而且效果也是显而易见的。

       在TFS中,Ns需要存放BlockDs之间的相互关系,比如对于某个Block来说,Ns需要知道该Block的几个副本位于哪些Ds上,而对于Ds来说,Ns需要知道该Ds下面包含哪些Block,以及哪些Block是可写的,以及哪些Block是满的等等,这样Ns就需要保存BlockDs之间的双向关系。针对具体的Block,早期的设计只保存Dsid列表,而针对具体的Ds,也只保存Blockid列表,这样的设计,还不足以准确判断Ds迅速上下线所带来的微小改变。因此后来做了对两者指针的相互关系引用,通过指针一方面可以方便地改变对方的状态,另一方面也便于检测Ds短时间内上下线所带来的微小变化,便于调试。这个优化会带来一定的负面作用,就是在检测BlockDs之间的关系时,需要小心考虑是用指针来判断还是用id来判断。

       对于TFS集群来说,我们肯定是希望集群越少进行数据迁移越好,毕竟迁移有可能导致很多意外情况的发生。因为数据是按照Block为单位进行迁移的,而Block在迁移的过程中肯定是不可写的,于是为了提供尽可能多的可写Block,之前有一种优化方案是只迁移那些被写满的Block,从数据的负载均衡和给客户端提供尽可能多的可写Block角度来说,方案是可行的,但是后来发现,这种负载均衡的方式对于访问来说就显的不够均衡了,因为被写满的Block往往都是比较旧的数据,访问的比较少,这样一来,大部分访问都没有落到包含写满BlockDs上,这样一来,就达不到分布式系统的要求了。另一个与之刚好相反的考虑是,比如上了一台新的机器,肯定会发生数据迁移,于是我们就想可以让挑选可写块的时候多挑中那些比较空的机器,这样一来,迁移发生的几率就小很多了,可是这样带来的问题和前面的刚好相反,新的机器上的数据都比较新,热点太集中也不能达到分布式系统的要求了。从这一点上看,出于对某一点考虑的优化很可能会带来另一方面的负面作用,所以优化还得从总体上权衡把握。

       之前有专门针对写的过程中造成Ns以及Ds之间Version不一致的情况的讨论,并且讨论结果认为Block version相差2被允许接受,    并不会对客户端访问数据造成影响,并且这样做也不会导致系统中大量的Block复制。但事实上,这里面还是存在一定问题的(说明极端情况在之前的讨论中没有考虑到)。比如目前有四个DsDs1Ds2在同一个机架,Ds3Ds4在同一个机架,Block aDs1Ds3上,客户端先发一个写请求,请求到的Blocka,成功返回文件名T1,接着Ds3长时间下线,Ns会在过了一定时间后发起复制Block的请求,假如这个时候Block a被复制到了Ds4上,然后又请求到a这个Block成功进行了写操作,得到文件名T2,接着Ds4下线,然后Ds3又上线了,这个时候按照Block version相差2的情况,Ds3上的Block a也被接受为一个副本,而这个副本中并没有T2文件的内容,然后Ds1长时间下线后,系统就会把Ds3Block a复制到Ds2上了,这样一来,文件T2就彻底找不到了,而我们的系统均是以写成功的方式返回给客户端的,系统就应该保证这个文件时不能丢的。所以说这个问题还是需要我们着手去解决的。

与之相类似的问题,当系统中存在一个副本时,对于指定的文件进行更新和删除操作都是可以进行的,这样一来,如果更新的文件所在的Block丢了之后,而另一个副本刚好又是更新前的那个Block,这样一来当用户试图读更新后的文件数据时,返回的将是更新前的数据。

       Ds的启动加载优化也是值得一提的。当系统中的数据量比较少的时候,原先的启动加载还看不出有多慢,但是随着数据量的增多,一个Ds的启动就需要十几分钟,那是因为之前的启动加载都是从各个不同的物理块文件头部进行读,相当于走的是磁盘的随机读,由于从每个文件中读的数据长度都是一致的,所以每个物理块前面的头部数据可以集中地放到统一的一个文件中,将原来的随机IO转成顺序IO的方式,使得原来的加载从十几分钟迅速提升到了几分钟,优化的效果可见一斑。

接下来,为了提高Ns的处理能力,还需要将Ns中涉及压缩、创建Block的部分逻辑交给Ds来完成。另外,为了提高Ds的写能力,还需要优化写操作的逻辑,这其中还涉及到优化Ds中的数据结构。

对于分布式存储系统来说,副本、数据一致性、协议等问题等都是由来已久的问题,只是针对不同的应用需求和场景,不同的系统有自己不同的考虑,在这些方面,可以多花时间研究需求,做好对应的优化。  

原创粉丝点击