写在前面
术语说明
EC 的全称是Erasure Code——纠删码,是一种编码理论,EC 介绍链接
如下是和本文档相关的一些术语:
- EC 策略:一般就是我们常说的(K+M),K 个数据块,M 个校验块
- 条带(stripe):和磁盘阵列中的条带类似,是把连续的数据分割成相同大小的数据块,把每块数据分别写入到 Ceph EC 中的不同磁盘上,EC 会针对这些数据块计算校验块,1 个条带包含多数据块和多个校验块,数据块的个数一般称为 K,校验块的个数称为 M,每个条带包含 (K + M) 块
- Ceph中 其他概念,包括:Monitor、OSD、scrub 等,可以参见 Ceph 官方文档:https://Ceph.io/
EC 的选择
- 选择 EC 的首要出发点是降低单位存储成本,比起传统的 3 副本存储方式,选择 8 + 3 EC 策略,存储副本数变为 1.375( 11 / 8),节约了 1.625 的存储副本
- 同时相比三副本的存储方式(不管是客户端直接写 3 副本,还是由复制组中的 master 节点接收数据后写两个 secondary 节点)写入流量减少将近 1 倍
近线存储实践
2019 网易数帆对象存储(内部代号 NOS)团队基于 Ceph EC 开发了近线存储引擎,针对原生的 Ceph EC 作了一系列优化,主要包括:
- 开发了 ECMgr 管控模块,负责分配 Ceph 写入 oid,配合 monitor 反向通知机制,解决 osd failover 和容量分布不均及降级写等问题
- 优化 librados 库,实现 smart-client-read 和 fast read 功能,在客户端做请求的分包、组包以及 EC 计算等,解决 master 压力过大和 IO 长尾问题
- 实现 dir-cache,在 Ceph 服务端对目录进行缓存,降低 IO 延迟
- 实现独立的 GC 模块,通过业务层的 rewrite 操作,实现底层 append Ceph 对象的空洞垃圾回收
近线存储是网易数帆使用 Ceph EC 的初次尝试,用于存储低频数据,满足了近线存储的要求;但整体上还存在两个比较严重的问题:
- 吞吐能力不足,IOPS 低 ,客户读带宽峰值 2GB / s 慢请求增多(常规读流量 500MB/s - 1GB/s)
- GC 效率低下,GC 过程需要通过读取所有数据片以反序列化对象信息,判断 Ceph 块是否可以回收,IOPS 和流量放大问题严重
不能满足在线存储场景,我们在近线存储优化的基础上针对在线存储场景也做了多项优化工作,本文介绍这些优化的实践、效果以及我们的心得。
小对象合并
从 NOS 的对象大小统计分布情况看,我们 80% 的对象大小都在 0 ~ 128KB 范围内,小对象的高占比是我们可以做对象合并的基础前提。

而从对象大小的角度来看在线存储比近线存储区别在于:
- 小对象:一般是低于 128KB 的,比如图片、文本,这一类对象,要求是 TPS
- 大对象:一般是大于 128KB 的文件,更重视整体的带宽吞吐
当前 NOS 在线存储的性能指标要求:
- 整体 TPS:30000+,读写占比符合28定律:20%写请求,80%读请求
- 小对象 latency:读 < 100ms,写 < 200ms(90分位值)
- 大对象吞吐:读 > 10GBps,写 > 1GBps(总体带宽)
而基于固有的近线存储架构不可能满足上述要求。由于 EC 必须要条带对齐,对 NOS 小对象来说,独占条带会严重降低有效数据利用率,所以我们的优化目标是小对象合并,通过合并对象写入,降低写 IOPS。
- 横向搁置条带策略
此方式在应用层累积对象,如 64kb 的条带,非合并方式下每个对象调用一次 write ;而在应用层累积多个对象后写入,如设置 1MB 的累积 buffer,当 buffer 写满后再批量调用 write ,按照平均大小 128KB 计算,可以将 8 个 IO 合并成 1 个,能显著降低写 IOPS 压力,如图(a) 所示。但此时一个对象仍然是分布在一个条带中,如图 (b) object-s1 - object-sn,读操作需要读取 n 个 osd。
