TFS集群数据对比

TFS没有采用目前流行的3副本策略,而是使用集群内配置2个副本,并把数据同步到一个辅集群,辅集群同样配置2个副本;这种方式对于实现异地机房容灾很方便,辅集群的数据同步是由主集群的数据服务器在后台发起的;目前主集群可读写,辅集群只读,双集群同时读写功能已开发完成,但没有在线上使用。

由于数据同步到辅集群是异步操作,当某次读文件的操作落到辅集群上时,可能该文件的同步尚未完成,此时在辅集群上读不到数据,这个问题目前是通过失败后在集群间重试来避免(迭代);还有一种方式就是当辅集群发现文件不存在时,主动去辅集群同步(递归),同步完成后向用户返回数据;这样做逻辑虽然正确,但存在几个问题:(1)在用户的一个请求中,递归的从主集群同步文件数据,如果文件较大,会导致用户请求超时;(2)将主辅集群间的同步协议复杂化了,当辅集群指定同步某个文件(而不是按主集群接收到请求的顺序),会打乱同步时序逻辑,从而爆发一些问题;比如文件是经过写(A)、更新(B)等操作才到达目前的状态,那么在同步到辅集群后,下次数据服务器(DS)重放日志同步时,写操作(A)实际上变成了更新操作;另外TFS还支持用户删除、隐藏文件,这些操作组合跟写组合到一起时,会产生更多微妙的问题。

主辅集群的所有副本,可能会发生一些数据不一致的问题,先讨论下集群内的不一致情况

  1. 某个数据服务器上内存、磁盘错误可能导致数据出现变化,这个问题目前通过写磁盘前检查文件crc来避免;
  2. 写多个副本只有master成功,其它slave副本都失败;由于TFS的集群内写操作是多个副本强一致性的(理论上),出现这种情况,会向用户返回失败信息,用户根本不知道这个文件的存在,这种不一致不会引发问题;
  3. TFS删除、隐藏操作在master副本上保证状态正确,在slave副本上的状态是不保证的;可能某个文件删除了,但其在某些副本上依然存在;由于文件的更新只会有master完成再同步到slave副本上,所以文件即使在slave上存在但不会被更改了,同时用户删除了文件通常不会再访问了,恶意用户因为不知道该文件对应的TFS文件名,所以也访问不到文件。
  4. 某个副本丢失,这个会有后台的复制任务来完成副本的复制,以保证数据的安全。

对于集群内的数据不一致,都有相应的处理措施,但集群间数据的维护是独立进行的,相互间没有影响,一旦出现主辅数据不一致的情况(出现几率较小),没有任何措施来处理。集群间数据对比工作主要目的在于发现集群间数据的不一致,并进行处理。

集群对比最简单的方式就是逐个block进行对比(逐个文件的方式不现实),目前最大的集群使用的block数约为850w,获取一个block上所有文件的信息(需要遍历block)约50ms,一次全量对比的时间约5天(持续不间断请求的理论值),如果每次都进行全量的对比显然是不能接受的,必须引入增量式的检查方案。

数据不一致主要出现在数据修改时,要实现增量式的对比,只需对比修改过的block即可,主要设计思想如下:

  1. DS记录修改的block。
  2. 增加checkserver收集DS修改的block信息并合并对比。
  3. 根据对比结果进行相应处理。

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,则需要从另一个集群同步过去。但这个策略存在很多问题:

  1. 可能某次检查,某个修改的block在主集群上稳定了,在被集群还没稳定(且很快就会变成稳定状态),这时CS就认为这个block需要同步到备集群,而这个同步过程显然是多余的。最开始跟@daoan讨论的方案是增加一个overlap的检查时间(2次检查有一段重叠时间),但这样就无法区分block需要同步还是刚好出现上述的临界状态。
  2. 针对某个DS的检查请求,由于网络等原因失败,但实际上一切正常,这时CS也会发现block在某个集群上不存在,认为其需要同步,而这个同步过程同样是多余的。
  3. block可能在某个集群上发生了压缩,或是某个文件在主集群上写后,在写同步前又删掉了,这时直接根据index中的文件数和文件总和来对比block是不准确的。

从上面的3点可以看出,通过获取hook的block,并从index获取文件信息是不准确;要想真正判定两个block数据不一致,必须排除掉block中被删除的文件,这就需要遍历整个block(开销比遍历index大很多);最终的实现方案是:首先CS执行一次检查,收集block信息,并对比进行一次初筛,对于数据可能不一致的block,将其加入到一个recheck list中,最后对于recheck list中的所有block,进行更细节的对比(排除删除文件的影响),如果发现block数据仍不同,则认为需要同步。

最后,集群同步工具根据CS的检查结果,对需要同步的block进行同步,使整个集群达到一致的状态。

转载于:https://www.cnblogs.com/yunnotes/archive/2013/04/19/3032316.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/421851.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

匿名类接口对象

interface MyInter1{public abstract void show();public abstract void show1(); } class OUter{public void outer(){//接口引用指向自己的实现类对象,多态调用MyInter1 M new MyInter1(){public void show(){System.out.println("匿名类对象show");}p…

Sesame 2.7.0 发布,Java 的 RDF 开发包

Sesame 2.7.0 开始使用 Maven Central,要求至少 Java 6 支持,SailConnection.begin() 指示事务开始,新的 Model 接口扩展了 Graph,OpenRDF Workbench 支持基本的 HTTP AUTHN,查询结果分页和保存查询结果,支…

(JAVA)Object类之toString()和equals()

Object类:存储于java.lang包中,有构造方法,无super 一.toString():返回该对象的字符串表示-----String类型,输出类型中,默认调用toString()1.public String toString() {return getClass().getName() "" I…

“四方定理”--蓝桥杯

欢迎访问我的新博客:http://www.milkcu.com/blog/ 原文地址:http://www.milkcu.com/blog/archives/1366349160.html 题目描述 标题:四方定理 数论中有著名的四方定理:所有自然数至多只要用四个数的平方和就可以表示。 我们可以通过…

(JAVA)Object类之Scanner

/* Scanner类&#xff1a;使用正则表达式解析基本类型和字符串的简单文本扫描器 一.源代码&#xff1a;public final class Scanner implements Iterator<String>, Closeable {...}1.不允许继承2.使用时必须导入包 import java.util.Scanner&#xff1b; jdk1.5以上版本才…

序列化 小复习

想要序列化一个对象则需要使其继承serializable或者externalizable接口 一下是一个实例小程序&#xff1a; ser_test 1 import java.io.*;2 3 public class ser_test{4 public static void main(String[] args) throws Exception{5 person p1 new person(1,1.2,&q…

windows设备坐标和逻辑坐标的转换

设备坐标通俗的讲就是我们看到的我们的视图坐标&#xff0c;它包含屏幕坐标、窗体坐标和客户区坐标&#xff0c;他们都是以窗体的左上角为准的坐标&#xff0c;并且是从左到右&#xff0c;从上到下的坐标 简单总结一下他的特点&#xff1a;x坐标是从左到右&#xff0c;y坐标是从…

(JAVA)Object类之String类

/* 字符串&#xff1a; 一、概述&#xff1a;1.字符串在JAVA中&#xff0c;使用""表示2.java.lang.String类3.只要写""就是字符串对象。不需要new二、空参构造器new Sting();private final char value[];public String() {this.value "".value;…

HADOOP__PIG安装与配置

PIG安装与配置 前提 已成功安装好Hadoop集群。 详见&#xff1a;http://www.cnblogs.com/freeideas/archive/2013/04/16/3023287.html 以下只在一个结点做&#xff0c;PIG可以直接调用整个集群。此处我选择了独立于其他节点的Server(CentOS)节点。 安装要求&#xff1a; Server…

(JAVA)String类之比较方法

/* 字符串&#xff1a; 一、概述&#xff1a;1.字符串在JAVA中&#xff0c;使用""表示2.java.lang.String类3.只要写""就是字符串对象。不需要new二、空参构造器new Sting();private final char value[];public String() {this.value "".value;…

(JAVA)String类之比较方法(2)

String类&#xff1a; 获取字符串的内容 一、获取字符串长度public int length() {return value.length;}length 与 lenght()的区别&#xff1a;前面是属性&#xff0c;不需要传参数后面是方法 二、指定下角标&#xff0c;返回固定位置的对应字符串public char charAt(int ind…

云计算之路-黎明前的黑暗:20130424网站故障经过

一、背景 4月18日的访问高峰扛过去之后&#xff0c;我们和阿里云一直在努力寻找问题的真正原因。是问题&#xff0c;躲不去的&#xff0c;不找到根源&#xff0c;随时会突然袭击。 压力测试未能重现问题&#xff0c;只能进行大海捞针般的猜测&#xff1a;SLB&#xff08;均衡均…

Sting练习

package com.book.lite;import java.util.Locale; import java.util.Scanner;/*1. 字符串的两种定义方式的区别:String a1 ""; 只有一个对象:String a2 new String(); 有两个对象2. String类的特点是什么底层代码的不变性&#xff0c;将字符串拆分成字符数组char[]…

枚举生成MVC3: Bind Enum To DropDownList ?-java教程

发一下牢骚和主题无关&#xff1a; 0. 预备测试数据 0.1 : 枚举 using System; using System.Collections.Generic; using System.Linq; using System.Web;namespace MvcApplication.Models {public enum YesOrNo{否 0,是 1} } 0.2 : 对应实体类及表sql using System; using…

(JAVA)StringBuffer类

可变数组&#xff1a;StringBuffer类(静态缓冲区) 提高字符串的操作效率 StringBuffer 底层实现原理是字符数组&#xff0c;没有final StringBuffer,含有数组char[] value 默认长度是16 在JAVA中&#xff0c;数组是固定长度&#xff0c;一旦创建不能改变 StringBuffer 通过数组…