Skip to main content

SN一致性校验方案

· 17 min read

首先遍历出所有的用户。

从用户角度出发开始做校验,。

请具体列明,而不要比如

先查出全网所有的总数,比如文件总数,文件长度,存储总量,实际占用空间等一些总量统计。将结果保存下来。

在再遍历所有的用户,分为用户级别、文件级别和数据块级别三个层次去读用户数据库,从本地或者缓存中去校验。

最后校验遍历用户过程中累计的总数与之前记录的总数有多大差异。由于校验过程中系统一直在运行,应该存在一定的差异,但该差异应在一个合理范围之内,对超出合理范围的差异生成警告性日志。

为减少上述差异,可记录一致性校验开始和结束期间新上传文件和新删除文件的总数,用来协助估算总数。

请列出具体算法。

开始做校验

第一层级用户级别。

此级别以用户为单位。对遍历到的每个用户:

1.先记录该用户的所有的总数(请补充具体字段filetotal 文件总数 spacetotal 存储总量 usedspace 实际占用空间)。

进行文件数,文件占用空间的校验。文件引用计数的校验,只要大于0就可以。如果等于0需要在核实下。核实方法还需在确定,暂未想好。累计全网的总数。

2.文件数校验,

首先查询metabase.users下面FileTotal字段得到该用户文件总数

其次统计usermeta.objects有多少条,一条记录代表一个文件。

将上述两个数进行对比。

还有namespace文件数校验。

\3. 遍历该用户namespace下的所有文件。遍历文件时每次读出若干数量的记录,该数量可配置,要尽量大使得对大多数用户可以一次读全,从而保证总量统计的一致性校验的准确性。对于文件总数非常多而且校验期间还有上传删除等操作的用户,就只能保证总量统计的一致性校验的相对准确性。

\4. 对遍历到的每个文件,读取对应的usermeta.objects记录(以下记为object),进行如下校验:

4.1文件引用计数的校验,验证object的NLINK是否大于0,否则记录错误日志。对于NLINK大于0但不准确的潜在问题,因为不影响使用且验证性能较低,暂时不做一致性验证。

对于NLINK应该为0却不为0的潜在问题,是否需要校验有待讨论。

4.2 验证文件元数据与object中的其它字段是否一致(请补充具体字段文件命名空间表和object表唯一可以校验的就是 ObjectID 其他没有可以进行对比校验的了。)

4.3 累计该用户的总数(filetotal 文件总数 spacetotal 存储总量 usedspace 实际占用空间例如存储总容量,请具体列明)

文件占用空间

首先查询metabase.users下面Usedspace字段得到该用户文件总占用空间

其次统计usermeta.objects中的Usedspace字段,加总。

将上述诉两个数进行对比

文件引用计数校验

首先查询usermeta.objects中NLINK大于0的字段

4.4 对该object自身进行一致性校验,即所述第二层级的文件级别校验。

\5. 遍历完所有文件后,对比遍历过程中累计的总数与之前记录的总数是否相同。大部分情况下应该相同,如果文件太多不能一次读完,就难以保证绝对一致性,可以参照校验期间该用户新上传的文件和新删除的文件来进行调整,使得正常情况下二者的误差率很低。还有一种可能的差异时读该用户总数之后、读该用户文件记录之前刚好发生了上传或删除,为此可以在发生小额差异时回头再读用户的总数,如果该总数与之前记录的总数相同,则基本可以确认存在不一致的数据(除非是读该用户总数之后、读该用户文件记录之前发生上传,校验期间发生删除,而且上传和删除的总量刚好相等,或者类似的先删除再上传),记录错误日志;如果该总数与累计的总数相同,则基本确认数据没错(除非发生类似的巧合);如果都不相同,则根据差额大小记录警告性日志或错误日志。

第二层级别文件级别。

此级别以文件为单位,对每一个object,

对遍历到每个文件先记录该文件下所有的总数,数据块总数,数据块长度。累计该用户下的总数。遍历该文件下所有的数据块。遍历文件时每次读出若干数量的记录,该数量可配置,要尽量大使得对大多数用户可以一次读全,从而保证总量统计的一致性校验的准确性。校验过程中如果有删除操作,就只能保证总量统计的一致性校验的相对准确性。

对遍历到的每个数据块读取对应的记录进行如下校验:

数据块引用计数的校验,验证数据块object的NLINK是否大于0,否则记录错误日志。对于NLINK大于0但不准确的潜在问题,因为不影响使用且验证性能较低,暂时不做一致性验证。

  1. 累计数据块长度校验,遍历object中blocklist中的值累计总数与之前所记录的总数进行对比校验。

对该数据块自身进行一致性校验,即所述第三层级的数据块级别校验。2,遍历完所有数据块后,对比遍历过程中验证各数据块累计的长度与object中记录的文件长度总数与之前记录的总数是否相同。大部分情况下应该相同,如果数据块太多不能一次读完,就难以保证绝对一致性。一种可能的差异是读该数据块总数之后、读该数据块记录之前刚好发生了删除,为此可以在发生小额差异时回头再读数据块的总数,如果该总数与之前记录的总数相同,则基本可以确认存在不一致的数据,记录错误日志;如果该总数与累计的总数不相同,则基本确认数据没错;如果都不相同,则根据差额大小记录警告性日志或错误日志。

进行数据块总数,数据块总长度,数据块引用计数的校验。数据块引用计数的校验,只要大于0就可以。如果等于0需要在核实下。在去查block表核实一下。

数据块总数校验

首先查询usermeta.objects表中Blocklist字段并解码得到两个数一个数数据数量,另一个事数据块BVI

其次通过BVI查询metabase.blocks表,统计结果数量

将上述两个数进行对比

数据块引用计数校验

首先遍历出metabase.blocks表NILINK=0的数据

首先用上面查询得到数据跟usermeta.objects表中Blocklist字段进行对比VBI

首先遍历出再去查询metabase.blocks表该VBI的数据块记录NILINK是否等于=0的数据

看收否能匹配上。

数据块分片数校验

首先查询usermeta.objects得到block.VBI和block.VNF利用分片ID的生成规则,制作出一个列表。

其次利用上面做出的列表去usermeta.shard表中查询。并统计结果

数据块长度的校验

查询usermeta.objects表中length字段

查询usermeta.objects表中Blocklist字段并解码出源长度并累加最后校验累加的数据块长度,与对应的文件长度是否一致。

第三层级别数据块级别

此级别以数据块为单位

对遍历到的每个分片读取对应的记录进行如下校验:

1分片所属矿机的校验,只要在SN端查出是否有记录就可以。也就是是否有对应的矿机存这个分片。

进行分片总数,分片所属矿机等的校验,

分片总数校验

首先查询usermeta.objects得到block.VBI和block.VNF利用分片ID的生成规则,制作出一个列表。

其次利用上面做出的列表去usermeta.shard表中查询。并统计结果

分片数量校验

这里分几个层级,数据块级(此级下分片数),文件级(此级下分片数),用户级等

首先查metabase.blocks得到VNF也就是分片数,利用分片ID的生成规则,

制作出一个列表。

用这个列表去shard表查询,统计并计算结果。

分片所属矿机校验

查询分片在哪个矿机上。是否有对应的矿机存储这个分片

---------------------------------------------------

文件数校验,

首先查询metabase.users下面FileTotal字段得到该用户文件总数

其次统计usermeta.objects有多少条,一条记录代表一个文件。

将上述两个数进行对比。

文件引用计数校验

首先查询usermeta.objects表下面NLINK=0的记录

其次查询metabase.blocks表里所属上面文件的数据块NLINK是否也是0

文件下数据块数量校验

首先查询usermeta.objects表中Blocklist字段并解码得到两个数一个数数据数量,另一个事数据块BVI

其次通过BVI查询metabase.blocks表,统计结果数量

将上述两个数进行对比

数据块引用计数校验

首先遍历出metabase.blocks表NILINK=0的数据

用上面得到数据跟usermeta.objects表中Blocklist字段进行对比

看收否能匹配上。

数据块分片数校验

首先查询usermeta.objects得到block.VBI和block.VNF利用分片ID的生成规则,制作出一个列表。

其次利用上面做出的列表去usermeta.shard表中查询。并统计结果

数据块数量校验

首先查询usermeta.objects表中Blocklist字段并解码得到两个数,一个数是数据数量,另一个是数据块VBI。并把VBI做成一个列表。

第二步用上面的列表去metabase.blocks表中查询,并计算结果

分片大小校验

当初想的是校验分片是否都是16K,不过这个好像没必要

分片数量校验

这里分几个层级,数据块级(此级下分片数),文件级(此级下分片数),用户级等

首先查metabase.blocks得到VNF也就是分片数,利用分片ID的生成规则,

制作出一个列表。

用这个列表去shard表查询,统计并计算结果。

分片所属矿机校验

首先查询metabase.shards表的到nodeid

其次用nodeid查矿机node表的到矿机的连接方式和IP

自写程序或者借助外部程序完成与矿机通信并尝试下载根据得到的结果进行校验

文件占用空间校验

首先查询metabase.users中usedspace字段的值。并取出用户ID

用mod()方法计算出这个用户所属的sn是哪一台。

去对应的sn上,查询这个用户的库中objects表中usedspace并统计结果。和上面的到的结果进行校验。

关于动态变化和超大数据量的补充:

动态变化

  1. 第一个方案,只校验历史数据。比如今天15号,在做校验的时候,只校验14号之前的数据。
  2. 第二个方案,是否可以起一个服务,监听变化数据,比如校验是A和B校验,在做完A的时候启动这个服务,然后开始B这边的校验。
  3. 第三个方案,就是在做校验的时候,不允许数据有变化,不知道这个是否可行。

大数据

  1. 第一个方案就是将大数据,拆成小数据。以一定的规则拆分。
  2. 第二个方案是是否可以通过提高并发数来减少处理大数据的时间。
  3. 第三个方案是,全量校验一个月或者半年,甚至一年做一次。其他时间只做增量,更新的校验。

以上:只是我初步的一个想法,不知道是否具有可行性,还请大家一块来讨论一下。

一致性校验的输出为日志,包括错误日志(肯定有错)、警告日志(可能有错)和统计日志(校验正确的就不一一记录日志,而是分阶段记录统计数据),有点像DOS下的chkdsk或杀毒软件。