复制
概述
容器复制是 Apache Ozone 中的一项关键机制,它通过将容器从源数据节点复制到目标数据节点来保证数据的可用性与持久性。本文档详细描述了复制过程,包括涉及的具体步骤、推送复制的优势,以及可以对 EC(纠删码)容器进行复制的场景。
复制模式
Apache Ozone 默认支持推送复制,即源数据节点主动将容器推送到目标数据节点。复制模式由配置项 hdds.scm.replication.push 控制(默认值:true)。当设置为 false 时,系统使用拉取复制,由目标数据节点从源数据节点拉取容器。
推送复制: PushReplicator 类通过以下方式处理推送复制:
- 使用
OnDemandContainerReplicationSource准备容器 - 使用
GrpcContainerUploader通过 gRPC 流上传容器 - 将容器数据直接流式传输到目标数据节点
note
普通容器复制和 EC 容器复制都遵循相同的 hdds.scm.replication.push 配置项。EC 容器复制场景(下线、副本不足、维护模式、副本分布错误)在配置为 true(默认)时使用推送模式,配置为 false 时使用拉取模式。
详细复制过程
容器复制过程包含若干明确的步骤。
步骤 1:源数据节点准备容器 tar 包
源数据节点创建一个包含以下内容的 tar 包:
- 容器描述文件(
container.yaml)及其元数据 - RocksDB 元数据文件(数据库文件)
- 容器数据块文件(实际数据)
- 容器校验和文件(如果存在)
压缩: 该 tar 包默认不进行压缩。可以通过 hdds.container.replication.compression 启用可选压缩(可选值:NO_COMPRESSION(默认)、GZIP、SNAPPY、LZ4、ZSTD)。
步骤 2:目标数据节点接收 tar 包
源数据节点通过 gRPC 将 tar 包流式传输到目标节点:
- 建立 gRPC 流连接
- 通过
SendContainerRequest消息按块流式传输数据 - 目标节点将数据块写入所选卷临时目录中的临时文件:
<volume-root>/tmp/container-copy/。这样,数据节点可以并行下载容器,而不会阻塞系统根驱动器。
在接收之前,目标节点会先选择一个卷,预留空间(2 倍容器大小) 以容纳 tar 包及其解压后的文件,并创建临时目录。
步骤 3:解包并存储容器文件
目标数据节点解压 tar 包:
- 读取并校验容器描述文件(
container.yaml) - 将 RocksDB 元数据解压到元数据目录
- 将数据块文件解压到数据块目录
- 将校验和文件(如果存在)解压到元数据目录
文件先被解压到临时目录,然后原子地移动到最终位置:<volume-root>/containerID/、<volume-root>/containerID/metadata/ 以及 <volume-root>/containerID/chunks/。
步骤 4:导入容器
容器被导入到数据节点的容器集合中:
- 根据元数据创建容器对象
- 将容器状态设置为
RECOVERING - 将容器与所选卷关联
- 将容器添加到
ContainerSet - 根据容器大小更新卷的使用量
- 调度按需扫描
系统会跟踪导入进度以防止并发导入。如果导入失败或容器已存在,则执行相应的错误处理。
步骤 5:删除临时文件
成功导入后,所有临时文件都会被清理:
- 删除压缩包:从临时目录中删除已下载的 tar 包文件
- 释放预留空间:释放卷上的预留空间
- 失败时清理:如果任何步骤失败,则删除临时文件并释放预留空间
推送复制的优势
推送复制具有以下几项优势:
- 更好的负载分布:源数据节点控制传输速率和时机,管理自身负载的同时简化了目标端的操作
- 更高的网络效率:借助 gRPC 流控的直接流式传输能适应网络状况,降低延迟
- 简化的故障处理:由源端负责重试和错误恢复,目标端只需处理传入的流
- 更好的资源管理:源端可根据自身容量(磁盘 I/O、CPU、网络)对传输进行限流,避免过载
EC 容器复制场景
纠删码(EC)容器有特定的复制要求,以及需要进行复制的特定场景。
场景 1:退役
发生时机: 当数据节点进入退役状态时,存储在该数据节点上的所有 EC 容器副本必须被复制到其他数据节点,然后才能安全地将该数据节点从集群中移除。
工作方式:
- 检测:
ECUnderReplicationHandler检测出副本位于正在退役数据节点上的容器 - 索引识别:处理器识别出哪些 EC 索引仅存在于正在退役的数据节点上(
decommissioningOnlyIndexes()) - 逐一复制:针对每个退役中的索引,创建一条复制命令,将该特定索引复制到新的数据节点
- 目标选择:根据放置策略选择新的目标数据节点
- 执行复制:每个索引独立复制,使用所配置的复制模式(默认为推送,可通过
hdds.scm.replication.push配置为拉取)
示例:
对于一个复制配置为 RS-6-3-1024k 的 EC 容器:
- 6 个数据块 + 3 个校验块 = 共 9 个索引
- 如果索引 2 仅存在于一个正在退服的 Datanode 上,则只需要复制索引 2
- 复制命令中包含
replicaIndex=2,用于指定要复制的索引
场景 2:副本不足(Under-Replication)
发生时机: 当 EC 容器针对某个特定索引的副本数少于要求的数量时,该索引需要被复制。
工作原理:
- 副本数量分析:
ECContainerReplicaCount分析当前的副本分布情况 - 缺失索引检测:找出副本数少于要求的索引
- 源副本选择:为缺失的索引选择健康的源副本
- 复制命令:使用配置的复制模式(默认为推送模式)创建复制命令,以恢复冗余度
场景 3:维护模式
发生时机: 当 Datanode 进入维护模式时,这些 Datanode 上的 EC 容器副本可能需要额外的副本,以便在维护期间保持冗余度。
工作原理:
与退服类似,但冗余度要求有所不同:
- 维护模式允许降低冗余度(通过
maintenanceRemainingRedundancy配置) - 复制操作使用配置的复制模式(默认为推送模式),确保在维护期间维持最低冗余度
场景 4:副本放置错误(Mis-Replication)
发生时机: 当 EC 容器副本被放置在违反放置策略的 Datanode 上时(例如,同一机架上的副本过多)。
工作原理:
- 放置校验:
ECMisReplicationHandler根据策略校验副本的放置位置 - 违规检测:找出违反放置约束的副本
- 复制以修正放置:使用配置的复制模式(默认为推送模式)创建复制命令,将副本移动到符合要求的位置
- 删除旧副本:复制成功后,删除旧副本
评论
登录后参与评论
KnowForge