@HUST张友东 work@taobao zyd_com@126.com
分类: 服务器与存储
2012-05-02 21:17:18
TFS没有采用目前流行的3副本策略,而是使用集群内配置2个副本,并把数据同步到一个辅集群,辅集群同样配置2个副本;这种方式对于实现异地机房容灾很方便,辅集群的数据同步是由主集群的数据服务器在后台发起的;目前主集群可读写,辅集群只读,双集群同时读写功能已开发完成,但没有在线上使用。
由于数据同步到辅集群是异步操作,当某次读文件的操作落到辅集群上时,可能该文件的同步尚未完成,此时在辅集群上读不到数据,这个问题目前是通过失败后在集群间重试来避免(迭代);还有一种方式就是当辅集群发现文件不存在时,主动去辅集群同步(递归),同步完成后向用户返回数据;这样做逻辑虽然正确,但存在几个问题:(1)在用户的一个请求中,递归的从主集群同步文件数据,如果文件较大,会导致用户请求超时;(2)将主辅集群间的同步协议复杂化了,当辅集群指定同步某个文件(而不是按主集群接收到请求的顺序),会打乱同步时序逻辑,从而爆发一些问题;比如文件是经过写(A)、更新(B)等操作才到达目前的状态,那么在同步到辅集群后,下次数据服务器(DS)重放日志同步时,写操作(A)实际上变成了更新操作;另外TFS还支持用户删除、隐藏文件,这些操作组合跟写组合到一起时,会产生更多微妙的问题。
主辅集群的所有副本,可能会发生一些数据不一致的问题,先讨论下集群内的不一致情况
对于集群内的数据不一致,都有相应的处理措施,但集群间数据的维护是独立进行的,相互间没有影响,一旦出现主辅数据不一致的情况(出现几率较小),没有任何措施来处理。集群间数据对比工作主要目的在于发现集群间数据的不一致,并进行处理。
集群对比最简单的方式就是逐个block进行对比(逐个文件的方式不现实),目前最大的集群使用的block数约为850w,获取一个block上所有文件的信息(需要遍历block)约50ms,一次全量对比的时间约5天(持续不间断请求的理论值),如果每次都进行全量的对比显然是不能接受的,必须引入增量式的检查方案。
数据不一致主要出现在数据修改时,要实现增量式的对比,只需对比修改过的block即可,主要设计思想如下:
DS要记录修改的block,须在改变block内容的接口上增加hook,目前只在写(包括更新)操作、以及块复制、压缩完成时增加hook,将修改block的id和修改时间记录到一个map中(修改block的信息只记录在内存上,它在block副本对应的所有机器上都会记录一份,这些修改信息即使丢失也不会对系统有影响,故不需要进行持久化存储),当checkserver(简称CS)发送check请求时,DS将上次检查到这次检查间隔内修改的block信息(文件数量、文件总大小等)回复给CS,CS将所有主辅集群上相同block的信息进行汇总并对比。
理论上DS每次返回block信息后,就可以将该段时间内修改的block数据删掉,但当集群DS数量很多时,如果CS在检查过程中宕机,这个检查过程是不能重现的(除非CS持久化从DS获取到的block信息),即使block间有不一致的情况,也只能在block下次被修改的时候发现。据不完全统计,2T的盘约有2.3w左右的block,由于每个block的元数据只有12B,即使所有block都被修改,总的数据占用内存也不会超过1M,对系统内存使用的影响不大;故为了简化CS,使其无状态,DS hook的block修改数据是不删除的。
CS的检查是一个周期性执行的任务,CS每次检查从上次检查后到本次检查时间间隔内的block,为了避免异步同步的影响(主集群上的写,还没有同步到辅集群),对每次检查block的条件再加了一个限制,修改了并且超过指定时间(认为其已经稳定了,如5min,可配置)没有修改,CS的检查间隔、block的稳定时间都是在CS上配置的,检查的目标时间段也在CS上计算好传至DS,避免修改配置项需要重启DS。
CS收集到DS上修改的block信息后,对blockid相同的信息进行合并,最后从每个集群选择version最高的block用于对比,通过对比发现主辅集群上block数据不一致时就需要对该block进行同步(该任务与检查分开进行)。关键问题是如何认定主辅集群上block不同?最简单的方法是,直接对比block上的文件数和文件总大小,对于在某一个block上不存在的block,则需要从另一个集群同步过去。但这个策略存在很多问题:
从上面的3点可以看出,通过获取hook的block,并从index获取文件信息是不准确;要想真正判定两个block数据不一致,必须排除掉block中被删除的文件,这就需要遍历整个block(开销比遍历index大很多);最终的实现方案是:首先CS执行一次检查,收集block信息,并对比进行一次初筛,对于数据可能不一致的block,将其加入到一个recheck list中,最后对于recheck list中的所有block,进行更细节的对比(排除删除文件的影响),如果发现block数据仍不同,则认为需要同步。
最后,集群同步工具根据CS的检查结果,对需要同步的block进行同步,使整个集群达到一致的状态。