Skip to content

分布式存储

RecordPlatform 采用故障域感知的分布式存储架构以实现高可用。

故障域架构

域类型

系统支持 N 个活跃域 + 1 个可选备用域 的灵活配置:

域类型说明接受写入用途
活跃域通过 active-domains 配置,支持 1~N 个数据写入目标
备用域通过 standby-domain 配置(可选)热备节点池

部署模式

模式活跃域数副本因子适用场景
单域模式11开发环境
双域模式22标准生产
多域模式3+可配置高可用生产

工作原理

  • 每个文件分片写入 N 个活跃域(每域一份)
  • 副本因子默认等于活跃域数量,可通过 storage.replication.factor 调整
  • N-1 域容错:任意 N-1 个域故障时系统仍可用
  • 活跃域性能下降时,备用域节点自动提升

一致性哈希

虚拟节点机制

配置项

属性默认值说明
virtualNodesPerNode150每个物理节点的虚拟节点数
replication.factor活跃域数量总副本数(不超过活跃域数量)
weight100节点权重(影响虚拟节点数)

优势

  • 均匀分布:虚拟节点使数据分布均匀
  • 最小迁移:增删节点仅影响 ~1/N 的数据
  • 加权分配:权重越高 = 虚拟节点越多 = 数据越多

直接分片上传晋升

直接分片上传通过预签名 PUT URL,将浏览器字节写入租户/会话范围的 staging 对象。完成操作不信任 URL 或客户端路径:platform-storage 会重建 canonical staging 身份,校验声明的大小和 SHA-256,再将对象晋升到内容寻址的最终 key。

  • 同端点目标使用条件式服务端 copy,并重新校验目标元数据。
  • 跨端点目标使用固定大小、带背压的流式传输,不会把整个分片聚合到堆内。
  • 晋升满足配置的副本 quorum。降级成功会持久化修复任务,不会声称所有副本健康。
  • 持久化 Redis receipt 使重复 complete 在进程重启后仍保持幂等。
  • complete、abort 和生命周期清理共用分片锁、不可变操作意图与 fencing token;过期 worker 无法删除或覆盖新一代对象。
  • staging/direct-upload 由专用生命周期独占,并从通用一致性修复中排除。

限制与生命周期默认值

配置默认值有效边界
storage.direct-upload.max-file-size-bytes4 GiB直传单文件上限
storage.direct-upload.max-part-size-bytes100 MiB直传单分片上限
storage.direct-upload.stream-buffer-bytes64 KiB限制在 8 KiB–1 MiB
storage.direct-upload.transfer-timeout-seconds300 秒最大 1,800 秒
storage.direct-upload.lock-wait-seconds5 秒最大 60 秒
storage.direct-upload.staging-retention-hours48 小时最小 48 小时,长于预签名 URL 生命周期
storage.direct-upload.cleanup-enabledtrue启用有界生命周期回收
storage.direct-upload.cleanup-interval-millis3,600,0001 小时
storage.direct-upload.cleanup-initial-delay-millis300,0005 分钟
storage.direct-upload.cleanup-batch-size200集群 claim 批量
storage.direct-upload.cleanup-claim-lease-seconds600 秒带 fencing 的清理 claim lease

清理流程先 claim 已到期生命周期记录,再获取同一分片锁并校验当前 fencing token;provider 返回 404 时按幂等成功处理。无法在 lease 预算内完成的工作会重新调度,失败记录保留到后续轮次。Abort 会创建 tombstone,阻止延迟到达的 complete 复活已删除的 staging 内容。

自动故障转移

故障转移流程

事件类型

事件触发条件操作
NODE_ONLINE健康检查通过更新状态
NODE_OFFLINE健康检查失败触发故障转移
NODE_DOMAIN_CHANGED备用节点提升数据再平衡

数据再平衡

再平衡类型

类型触发条件操作
MIGRATE_FROM_FAILED节点下线从其他活跃域复制到新目标
COPY_TO_PROMOTED备用节点提升复制相关数据到新节点
REBALANCE_TO_NEW新节点加入重新分布数据

再平衡过程

java
// 由 NodeTopologyChangeEvent 触发
@EventListener
public void onNodeTopologyChange(NodeTopologyChangeEvent event) {
    switch (event.getChangeType()) {
        case NODE_OFFLINE:
            migrateFromFailedNode(event.getNodeName());
            break;
        case NODE_DOMAIN_CHANGED:
            copyToPromotedNode(event.getNodeName());
            break;
    }
}

限流控制

  • 默认:10 对象/秒
  • 防止再平衡期间 I/O 饱和
  • 可通过 Nacos 配置

再平衡配置

yaml
storage:
  rebalance:
    enabled: true # 是否启用自动再平衡
    rate-limit-per-second: 10 # 每秒最大复制对象数(限流)
    cleanup-source: false # 再平衡后是否删除源数据(默认不删除)

状态持久化

再平衡状态通过 Redis 持久化,确保:

  • 多实例部署时状态同步
  • 服务重启后状态可恢复
  • 状态 TTL:24 小时

副本一致性修复

定期扫描各域,检测并修复跨域副本不一致。

修复流程

  1. 获取分布式锁(防止多实例并发)
  2. 遍历所有活跃域,收集对象列表
  3. 两两比较域间对象,找出缺失副本
  4. 从健康副本复制到缺失的域

一致性配置

yaml
storage:
  consistency:
    repair:
      enabled: true # 是否启用定时修复
      cron: "0 */15 * * * ?" # Cron 表达式(默认每 15 分钟)
      batch-size: 100 # 每批处理对象数
      lock-timeout-seconds: 600 # 分布式锁超时时间(秒)

节点配置

必需配置

yaml
storage:
  # 必须配置:活跃域列表(按优先级排序)
  active-domains:
    - domain-a
    - domain-b

  # 可选:外部访问端点(v3.2.0 新增)
  # 用于生成预签名 URL 时替换内部端点地址,解决跨网段(如 VPN)访问问题
  external-endpoint: https://s3-secondary.example.com

  # 可选:备用域(用于故障转移)
  standby-domain: standby

  # 副本策略配置(v3.1.0 新增)
  replication:
    factor: 2                     # 副本数量,默认=活跃域数量
    quorum: auto                  # 仲裁策略: auto|majority|all|具体数字

  # 降级写入配置(v3.1.0 新增)
  degraded-write:
    enabled: true                 # 允许降级写入
    min-replicas: 1               # 降级模式下的最小副本数
    track-for-sync: true          # 记录降级写入以便后续同步

NodeConfig 属性

yaml
storage:
  nodes:
    - name: node-a1 # 唯一名称(同时作为桶名)
      endpoint: http://s3-a1:9000
      accessKey: ${S3_ACCESS_KEY}
      secretKey: ${S3_SECRET_KEY}
      faultDomain: domain-a # 必须匹配 active-domains 或 standby-domain
      weight: 100 # 影响数据分布
      enabled: true # 是否加入哈希环
      metricsPath: /minio/v2/metrics/node # 健康指标端点

域配置(可选)

yaml
storage:
  domains:
    - name: domain-a
      minNodes: 1 # 触发提升的最少健康节点数
      replicaCount: 1 # 该域中每个分片的副本数
      acceptsWrites: true
    - name: domain-b
      minNodes: 1
      replicaCount: 1
      acceptsWrites: true
    - name: standby
      minNodes: 0
      replicaCount: 0
      acceptsWrites: false

完整配置示例

开发环境(单域模式)

yaml
storage:
  active-domains:
    - local
  nodes:
    - name: local-minio
      endpoint: http://localhost:9000
      accessKey: ${S3_ACCESS_KEY:?请在部署环境设置 S3_ACCESS_KEY}
      secretKey: ${S3_SECRET_KEY:?请在部署环境设置 S3_SECRET_KEY}
      faultDomain: local

生产环境(三域 + 备用)

yaml
storage:
  active-domains:
    - dc-beijing
    - dc-shanghai
    - dc-shenzhen
  standby-domain: standby
  replication:
    factor: 3

  nodes:
    - name: bj-node1
      endpoint: http://s3-bj:9000
      faultDomain: dc-beijing
    - name: sh-node1
      endpoint: http://s3-sh:9000
      faultDomain: dc-shanghai
    - name: sz-node1
      endpoint: http://s3-sz:9000
      faultDomain: dc-shenzhen
    - name: standby-node1
      endpoint: http://s3-standby:9000
      faultDomain: standby

负载感知读取选择

读取时,系统基于负载评分选择最优节点:

txt
负载评分 = (磁盘使用率 × 0.4) + (在途请求 × 0.35) + (等待请求 × 0.25)

评分越低 = 优先用于读取。

监控

关键指标

指标说明
s3_node_online_status节点在线/离线状态
s3_node_load_score计算的负载评分
s3_node_operations_total操作计数器

健康检查间隔

  • 节点健康检查:30 秒
  • 备用节点提升检查:30 秒
  • 指标缓存 TTL:60 秒

Released under the Apache 2.0 License.