Skip to content

数据表设计

1. SQLITE 特点

  1. 字符类型是 TEXT, 虽然支持 VARCHAR 但是长度约束无效,且本质上会转化为 TEXT
  2. sqlite 的 INTEGER, 会根据值的大小自动选择 1~8 字节存储

2. 详细数据库设计

  • 时间戳使用 unix 时间戳 (即单位为秒)
  1. 根目录索引 info_root

    归档的时候,需要把根目录写入索引表; 解档的时候,需要从索引表中选取需要解档的根目录。

    字段类型约束默认值备注
    idINTEGERPRIMARY KEY AUTOINCREMENT目录唯一标识
    root_nameTEXTNOT NULL目录名称
    root_pathTEXTNOT NULL根目录 (不是唯一,不同系统可能会重复)
    statusTEXTNOT NULL'HEALTH'状态:HEALTH/RECYCLED
    created_atINTEGERNOT NULLCURRENT_TIMESTAMP创建时间戳
    updated_atINTEGERNOT NULLCURRENT_TIMESTAMP更新时间戳
  2. 目录索引表 info_directory

    字段类型约束默认值备注
    idINTEGERPRIMARY KEY AUTOINCREMENT目录唯一标识
    root_idINTEGERNOT NULL REFERENCES root_index(id)目录根目录
    directory_nameTEXTNOT NULL''目录名 (TODO 是否需要)
    directory_mtimeINTEGERNOT NULL0修改时间 (unix 时间戳)
    directory_pathTEXT相对路径
    statusTEXTNOT NULL'HEALTH'状态:HEALTH/RECYCLED
    created_atINTEGERNOT NULLCURRENT_TIMESTAMP创建时间戳
    updated_atINTEGERNOT NULLCURRENT_TIMESTAMP更新时间戳
    • unique(root_id, directory_path)
  3. [Optional]目录树关系表 - 闭包表 (directory_tree)

    字段类型约束默认值备注
    ancestor_idINTEGERNOT NULL REFERENCES directory_index(id)祖先目录 ID
    descendant_idINTEGERNOT NULL REFERENCES directory_index(id)后代目录 ID
    depthINTEGERNOT NULL目录层级深度(0 表示自身)
    statusTEXTNOT NULL'HEALTH'状态:HEALTH/RECYCLED
    created_atINTEGERNOT NULLCURRENT_TIMESTAMP创建时间戳
    updated_atINTEGERNOT NULLCURRENT_TIMESTAMP更新时间戳
  4. 文件索引表 info_file

    • 硬链接所指的文件,和源文件仅路径和名称存在差异,hash,修改日期等都一致
    • 文件索引表中仅文件信息相关内容,不要有归档相关信息,和归档解耦,归档相关数据表单向引用文件索引表的内容
    字段类型约束默认值备注
    idINTEGERPRIMARY KEY AUTOINCREMENT文件唯一标识
    directory_idINTEGERNOT NULL REFERENCES directory_index(id)
    file_nameTEXTNOT NULL文件名 (不含路径)
    file_sizeINTEGERNOT NULL0文件大小 (字节)
    file_mtimeINTEGERNOT NULL0修改时间 (unix 时间戳)
    file_hashTEXThash/SHA256哈希值(可重复, 当文件内容相同,文件名不同时)
    statusTEXTNOT NULL'HEALTH'状态:HEALTH/RECYCLED
    created_atINTEGERNOT NULLCURRENT_TIMESTAMP创建时间戳
    updated_atINTEGERNOT NULLCURRENT_TIMESTAMP更新时间戳
    • UNIQUE (directory_id, file_name)
    • UNIQUE (directory_id, file_name, file_hash)
  5. 归档元数据表 archive_metadata

    字段类型约束默认值备注
    idINTEGERPRIMARY KEY AUTOINCREMENT归档 ID
    archive_uriTEXTNOT NULL归档存储 URI,每个归档可以自定义存储目录
    archive_nameTEXTUNIQUE NOT NULL归档名称,文件系统中的文件名
    archive_limit_sizeINTEGERNOT NULL归档限制大小(字节)
    archive_hashTEXT归档文件的 hash 校验值
    is_compressedINTEGERNOT NULL00=未压缩,1=已压缩
    compressed_algorithmTEXT压缩算法(如 gzip/zstd)
    is_encryptedINTEGERNOT NULL00=未加密,1=已加密
    encryption_algorithmTEXT加密算法(如 aes-256-cbc)
    statusTEXTNOT NULL'HEALTH'状态(HEALTH/RECYCLED/HASH_OUTDATED)
    created_atINTEGERNOT NULLCURRENT_TIMESTAMP创建时间戳
    updated_atINTEGERNOT NULLCURRENT_TIMESTAMP更新时间戳
    • archive_uri: 支持移动到网络驱动,所以在解档,以及数据巡检的时候需要额外操作,例如下载到本地等
  6. 归档内容表 archive_chunk

    • chunk_size 不包括 tar 格式文件头的信息,所以 chunk_size 的总和可能小于 archive_metadata.archive_limit_size 以及 archive_metadata 的实际尺寸
    字段类型约束默认值备注
    idINTEGERPRIMARY KEY AUTOINCREMENT归档数据块唯一标识
    archive_idINTEGERNOT NULL REFERENCES archive_metadata(id)关联的归档 ID
    chunk_nameTEXTNOT NULL UNIQUE归档数据块名称,一般为 hash 值和文件名不一致
    chunk_sizeINTEGERNOT NULL0逻辑数据块大小 (字节),非实际占用 (压缩,加密会影响实际大小)
    chunk_hashTEXTNOT NULL UNIQUE归档数据块的 hash 必须计算,否则后续要计算得先解档
    chunk_mtimeINTEGERNOT NULL0修改时间 (unix 时间戳)
    chunk_relative_pathTEXTNOT NULL'./'数据块在归档内的相对路径
    statusTEXTNOT NULL'HEALTH'状态:HEALTH/CLOSED/RECYCLED/DRAFT
    created_atINTEGERNOT NULLCURRENT_TIMESTAMP创建时间戳
    updated_atINTEGERNOT NULLCURRENT_TIMESTAMP更新时间戳
    • 由于文件添加到归档中一般不分层级,所以要求使用 id 或 hash 重命名文件,并存储到归档中,文件名要求唯一
  7. 文件与归档数据块表 map_file_chunk

    • 当文件体积过大被拆分时,一份文件可能对应多个归档和分卷数据块。
    • 当文件重复时,一份数据块可能对应多份文件。
    • 分卷是针对文件 file, 归档并不会识别出这个数据块是分卷数据块还是普通数据块
    字段名类型约束默认值说明
    idINTEGERPRIMARY KEY AUTOINCREMENT NOT NULL
    file_idINTEGERNOT NULL REFERENCES file_index(id)
    chunk_idINTEGERNOT NULL REFERENCES archive_chunk(id)
    volume_orderINTEGERNOT NULL1分卷顺序编号
    statusTEXTNOT NULL'HEALTH'状态:HEALTH/CLOSED/RECYCLED
    created_atINTEGERNOT NULLCURRENT_TIMESTAMP创建时间戳
    updated_atINTEGERNOT NULLCURRENT_TIMESTAMP更新时间戳
  8. 灾备组 disaster_recovery_group

    字段名类型约束默认值说明
    idINTEGERPRIMARY KEY AUTOINCREMENT
    group_idTEXTNOT NULL UNIQUE灾备组 UUID
    num_data_shardsINTEGERNOT NULL数据分片数量
    num_parity_shardsINTEGERNOT NULL校验分片数量
    shard_sizeINTEGERNOT NULL分片大小
    data_shards_storedINTEGERNOT NULL0是否存储数据分片
    statusTEXTNOT NULL'HEALTH'状态
    last_verifiedINTEGER最后校验时间戳
    created_atINTEGERNOT NULLCURRENT_TIMESTAMP创建时间戳
    updated_atINTEGERNOT NULLCURRENT_TIMESTAMP更新时间戳
  9. 数据分片 disaster_recovery_data_shard

    字段名类型约束默认值说明
    idINTEGERPRIMARY KEY AUTOINCREMENT NOT NULL
    group_idINTEGERNOT NULL REFERENCES disaster_recovery_group(id)灾备组 ID
    shard_indexINTEGERNOT NULL分片索引
    shard_pathTEXT分片路径(可为空)
    shard_hashTEXTNOT NULL分片哈希值
    statusTEXTNOT NULL'HEALTH'状态:HEALTH/CORRUPTED/MISSING
    last_verifiedINTEGER最后校验时间戳
    created_atINTEGERNOT NULLCURRENT_TIMESTAMP创建时间戳
    updated_atINTEGERNOT NULLCURRENT_TIMESTAMP更新时间戳
    • unique: (group_id, shard_index)
    • shard_index 用于标识分片顺序,reed-Solomon 对于分片有顺序要求
  10. 校验分片 disaster_recovery_parity_shard

    字段名类型约束默认值说明
    idINTEGERPRIMARY KEY AUTOINCREMENT NOT NULL
    group_idINTEGERNOT NULL REFERENCES disaster_recovery_group(id)灾备组 ID
    shard_indexINTEGERNOT NULL分片索引
    shard_pathTEXTNOT NULL分片路径(不能为空)
    shard_hashTEXTNOT NULL分片哈希值
    statusTEXTNOT NULL'HEALTH'状态:HEALTH/CORRUPTED/MISSING
    last_verifiedINTEGER最后校验时间戳
    created_atINTEGERNOT NULLCURRENT_TIMESTAMP创建时间戳
    updated_atINTEGERNOT NULLCURRENT_TIMESTAMP更新时间戳
    • unique: (group_id, shard_index)
    • shard_index 用于标识分片顺序,reed-Solomon 对于分片有顺序要求
  11. 归档文件与数据分片映射表 map_archive_data_shard

    这是一个用于明确关联灾备组中每个数据分片与其对应原始归档文件的映射表,解决通过 shard_index 隐式关联的问题。

    字段名类型约束默认值说明
    idINTEGERPRIMARY KEY AUTOINCREMENT NOT NULL
    shard_idINTEGERNOT NULL REFERENCES disaster_recovery_data_shard(id)数据分片 ID
    archive_idINTEGERNOT NULL REFERENCES archive_metadata(id)原始归档文件 ID
    archive_orderINTEGERNOT NULL归档文件顺序
    original_archive_hashTEXTNOT NULL创建分片时, 归档文件哈希值
    statusTEXTNOT NULL'HEALTH'状态:HEALTH/CORRUPTED/MISSING
    created_atINTEGERNOT NULLCURRENT_TIMESTAMP创建时间戳
    updated_atINTEGERNOT NULLCURRENT_TIMESTAMP更新时间戳
    • UNIQUE (shard_id, archive_id)
    • archive 可能有多个 data shard, 因为不同的 group 的最大文件大小不一样,所以即使相同的 archive 对齐后的 data shard 也不一定一样
    • original_archive_hash 是创建灾备时,归档文件哈希值,避免 archive 改变 (增减内容,或者灾备恢复,破损等), archive metadata 中的 hash 值更新,导致数据不一致
    • 关于 archive, data shard 的关系:
      • [TODO] (目前还是一对一) archive 可能被拆分为多个 data shard; 但不会多个 archive 合并为同一个 data shard
    • 关于 group 与 shard 的关系:
      • 每个 data shard 仅属于单个灾备组,但不同或者同一灾备组中的 data shard 可能具有相同的内容和 hash 值
      • 一个 group 会有多个 data shard
      • TODO 目前每个 shard 都是独立存储,之后再考虑是否需要合并
    • 关于 archive 与 group 的关系 (从数据库层面以及代码编码层面,两者没有直接关系,但是从用户层面,archive 和 group 存在关系)
      • archive 可能属于多个 group; 且 group 中 archive 可能会重复
    • TODO 需要考虑针对单个文件分块创建灾备组的情况
    • TODO 如果需要增加对于 archive 分块,需要调整灾备恢复 reporter 的逻辑,需要调整计算分片可用性的相关逻辑

视图

  1. 文件列表视图 view_file

    • file 是最小单位
    字段名类型描述
    root_idINTEGER根目录 ID
    root_pathTEXT根目录路径
    root_statusTEXT根目录状态
    directory_idINTEGER目录 ID
    directory_pathTEXT目录相对路径
    directory_mtimeINTEGER目录修改时间
    directory_statusTEXT目录状态
    file_idINTEGER文件 ID
    file_nameTEXT文件名
    file_sizeINTEGER文件大小
    file_mtimeINTEGER文件修改时间
    file_hashTEXT文件哈希值
    file_statusTEXT文件状态
  2. 数据块列表视图 view_chunk

    • chunk 是最小单位
    字段名类型描述
    archive_idINTEGER归档 ID
    archive_uriTEXT归档目录
    archive_nameTEXT归档名
    archive_statusTEXT归档状态
    chunk_idINTEGER数据块 ID
    chunk_nameTEXT数据块名
    chunk_sizeINTEGER数据块大小
    chunk_hashTEXT数据块哈希值
    chunk_mtimeINTEGER数据块修改时间
    chunk_relative_pathTEXT数据块相对路径
    chunk_statusTEXT数据块状态
    file_idINTEGER文件 ID
    volume_orderINTEGER分卷顺序编号