写入管道
写入管线是 Apache Ozone 存储架构的基础组件,能够在分布式节点之间实现可靠的数据存储。本文档对写入管线进行了全面概述,涵盖复制与纠删码两种方式、其架构、实现细节以及使用模式。
什么是写入管线?
写入管线是协同工作的 Datanode 组,它们作为一个整体在 Ozone 中存储和复制数据。它们是 Ozone 数据冗余策略的基础,提供:
- 跨多个节点的写操作协调路径
- 数据复制的一致性保证
- 数据分发与存储的高效管理
存储容器管理器(Storage Container Manager,SCM)负责创建和管理写入管线,根据可用性、容量和网络拓扑等因素选择合适的 Datanode。
管线类型
Ozone 支持多种类型的写入管线,以满足不同的持久性和存储效率需求:
1. Ratis 管线(复制型)
Ratis 管线使用 Apache Ratis 实现的 Raft 共识协议,实现强一致性复制。
- 结构:通常由三个 Datanode 组成(一个领导者,多个跟随者)
- 一致性:通过同步复制提供强一致性
- 持久性:数据在管线中的所有节点上完整复制
- 使用场景:大多数 Ozone 部署的默认复制策略
使用 Ratis 异步 API 在多个数据节点之间进行数据复制:
- 客户端在本地缓冲数据,直到达到某个阈值
- 数据被发送到管道中的主数据节点
- 主节点将数据复制到从数据节点
- 当多数数据节点确认写入后,该操作即视为成功
这种方法保证了数据一致性,但在网络拓扑感知和缓冲区处理效率方面存在一些局限性。
Ratis 管道 V2:流式 API
Ozone 中较新的流式写入管道(V2)利用 Ratis 流式 API,带来了显著的性能提升:
关键增强:
- 更好的网络拓扑感知能力
- 消除不必要的缓冲区复制(Netty 零拷贝)
- 提升数据节点上 CPU 和磁盘的利用率
- 数据处理中更高效的并行化
流式写入管道引入了一种新的网络协议,支持数据从客户端直接流式传输到数据节点,从而减少开销并提升吞吐量。
配置:
要启用流式写入管道(V2),请在 ozone-site.xml 中配置以下属性:
<property>
<name>hdds.container.ratis.datastream.enabled</name>
<value>true</value>
<description>Enable data stream of container</description>
</property>
<property>
<name>hdds.container.ratis.datastream.port</name>
<value>9855</value>
<description>The datastream port number of container</description>
</property>
<property>
<name>ozone.fs.datastream.enabled</name>
<value>true</value>
<description>Enable filesystem write via ratis streaming</description>
</property>2. 纠删码管线
纠删码(Erasure Coded,EC)管线利用数学技术,在存储开销低于完全复制的情况下实现数据持久性。
- 结构:将数据分片与校验分片分布到多个 Datanode 上
- 效率:所需存储空间少于完全复制(例如,50% 的开销,而非 200%)
- 恢复:可以从可用分片的子集中重建数据
- 适用场景:针对存储效率至关重要的大型数据集进行优化
条带化与数据布局
Ozone 中的 EC 采用条带化数据模型,其过程如下:
- 数据被划分为固定大小的块(通常为 1MB)
- 这些块被组织成条带(Stripe)
- 针对每个条带计算校验块
- 这些块被分布到各个 Datanode 上
例如,采用 RS(Reed-Solomon)6-3 配置时:
- 数据被切分为 6 个数据块
- 计算出 3 个校验块
- 这 9 个块共同构成一个“条带”(Stripe)
- 使用同一组 Datanode 的多个条带构成一个“BlockGroup”
这种方法相比 3 副本的 200% 存储开销,只需 50% 的存储开销,同时能提供相近的持久性保证。
纠删码配置
要在 Ozone 中使用纠删码(Erasure Coding,简称 EC),可以在存储桶级别或单个对象级别进行配置:
在创建存储桶时设置纠删码:
ozone sh bucket create <bucket path> --type EC --replication rs-6-3-1024k更改现有存储桶的 EC 配置:
ozone sh bucket set-replication-config <bucket path> --type EC --replication rs-3-2-1024k创建 Key 时设置 EC:
ozone sh key put <Ozone Key Object Path> <Local File> --type EC --replication rs-6-3-1024k支持的纠删码(EC)配置包括:
RS-3-2-1024k:Reed-Solomon 编码,3 个数据块、2 个校验块,块大小 1MBRS-6-3-1024k:Reed-Solomon 编码,6 个数据块、3 个校验块,块大小 1MB(推荐)XOR-2-1-1024k:XOR 编码,2 个数据块、1 个校验块,块大小 1MB
写入流水线生命周期
写入流水线遵循一个明确定义的生命周期,由存储容器管理器(Storage Container Manager,SCM)进行管理:
- 创建:SCM 选择合适的 Datanode 并创建流水线
- 活跃:流水线接受写操作并管理副本复制
- 关闭中:当流水线达到容量限制时,停止接受新的写入
- 已关闭:所有写操作完成后,流水线变为只读状态
- 恢复/重建:如果某个节点发生故障,SCM 可能会启动恢复流程
写入流水线的工作原理
Ozone 中的写操作通过流水线按以下步骤执行:
- 客户端请求:客户端联系 Ozone Manager(OM)以创建键或写入键
- 块分配:OM 向 SCM 请求分配块
- 流水线选择:SCM 为该写操作选择一条合适的流水线
- 数据传输:客户端将数据直接流式传输到流水线中的主(leader)Datanode
- 副本复制:对于 Ratis 流水线,主节点使用 Raft 协议将数据复制到从(follower)节点;对于 EC 流水线,客户端将不同的块分发到不同的 Datanode
- 确认:当所有副本都写入完成后,客户端会收到确认
实现细节
复制流水线实现
复制写入流水线通过以下几个关键类实现:
- BlockOutputStream:管理整体写入过程的基类
- RatisBlockOutputStream:实现 Ratis 特有的复制功能
- CommitWatcher:跟踪流水中所有数据节点的提交状态
- XceiverClient:负责与数据节点进行通信
写入过程遵循以下步骤:
- 客户端为已分配的块创建一个
BlockOutputStream - 数据按块(chunk)写入,并在本地缓冲
- 当缓冲区填满或触发刷新时,数据被写入数据节点
- 每个块被分配一个递增的序号并计算校验和
- 所有数据写入完毕后,通过 putBlock 操作完成该块的最终提交
EC 流水线实现
EC 写入流水线的实现涉及以下几个关键组件:
- ECKeyOutputStream:管理 EC 写入的主要客户端类
- ECChunkBuffers:为数据块和校验块维护缓冲区
- ECBlockOutputStreamEntry:管理数据节点的连接和写入操作
- RawErasureEncoder:执行数学编码以生成校验块
EC 写入过程遵循以下步骤:
- 数据缓冲:客户端将接收到的数据缓存为块(chunk)
- 条带形成:当一个条带的所有数据块都填满后,生成校验块
- 并行写入:数据块和校验块被并行写入不同的数据节点
- 提交:所有块写入完成后,提交该条带
容器与流水线
容器是 Ozone 中的基本存储单元,理解它与流水线之间的关系至关重要:
- 每个容器(通常为 5GB)都与特定的流水线相关联
- 单条流水线中可以存在多个容器
- 当容器处于 OPEN 状态时,它通过其流水线持续接收数据
- 容器进入 CLOSED 状态后,其数据可以通过任意副本节点访问
复制与纠删码的比较
| 特性 | 副本机制(RATIS/THREE) | 纠删码(RS-6-3) |
|---|---|---|
| 存储开销 | 200%(3 份副本) | 50%(6 个数据块对应 9 个块) |
| 写入性能 | 小写入吞吐量更高 | 大型顺序写入表现更佳 |
| 读取性能 | 性能稳定,任意副本均可提供服务 | 完整数据时略低,数据块丢失时有重建开销 |
| CPU 使用率 | 较低 | 较高(编解码开销) |
| 网络带宽 | 写入时较高 | 写入时较低 |
| 最少节点数 | 3 | 取决于配置(RS-6-3 需要 9 个) |
| 适用场景 | 热数据、随机访问、小文件 | 温/冷数据、大文件、归档 |
何时使用副本机制:
- 频繁访问的"热"数据
- 小数据随机写入的工作负载
- 原始写入性能至关重要的场景
- CPU 资源有限的场景
何时使用纠删码:
- 访问频率较低的"温"数据或"冷"数据
- 具有顺序访问模式的大文件
- 在保证持久性的同时优化存储成本
- 归档或备份存储
高级主题
错误处理与恢复
两种写入管道都实现了完善的错误处理机制:
副本管道:
- 使用 Ratis 共识协议处理故障
- 少数 DataNode 故障时可自动恢复
- 支持 Leader 故障时的管道重建
- 实现幂等操作以支持重试
纠删码管道:
- 以单个块(chunk)级别跟踪故障
- 可对失败的 DataNode 重试特定块的写入
- 维护条带状态以确保一致性
- 实现校验和验证以保证数据完整性
性能注意事项
优化副本写入管道:
- 根据工作负载调整缓冲区大小(
hdds.client.buffer.size.max) - 为写密集型工作负载配置刷写周期
- 在高吞吐量场景中使用流式管道(V2)
- 部署 DataNode 时考虑网络拓扑
优化纠删码写入管道:
- 根据工作负载特征选择纠删码配置
- 启用 ISA-L 硬件加速以获得更好性能
- 调整块大小以获得最佳性能
- 在并行度和开销之间取得平衡
监控与指标
两种写入管道都暴露了可通过 Ozone 的 Prometheus 端点或 JMX 接口进行监控的指标:
副本管道的关键指标:
- 写入吞吐量
- 平均分块写入延迟
- 管道创建时间
- Ratis 共识延迟
EC 管道的关键指标:
- 每条条带的编码时间
- 分块分布延迟
- 首次条带写入的成功率
- 奇偶校验计算开销
写入管道的优势
Ozone 中的管道架构提供了几项关键优势:
- 可靠性:自动的故障检测与恢复机制
- 一致性:对数据复制提供强一致性保证
- 可扩展性:高效管理横跨数千个节点的写入操作
- 灵活性:根据需求支持不同的复制策略
- 性能:优化的数据流路径,最大限度降低网络开销
结论
写入管道是 Apache Ozone 数据冗余架构的核心,确保数据在集群中被可靠地存储和复制。通过了解写入管道的工作原理,管理员和用户可以对其 Ozone 部署做出明智的决策,并针对特定使用场景进行有效调优。无论您需要的是复制带来的极致性能,还是纠删码带来的存储效率,Ozone 的写入管道都能为持久且一致的数据存储奠定基础。
评论
登录后参与评论
KnowForge