问题描述
在 Ceph 中,默认的数据保护机制是副本。但是,副本的缺点是需要占用多倍的存储空间来提供冗余。例如,计划搭建 replica=3 的 1PB 可用容量的存储集群,则需要准备 3PB 的存储容量,也就是 +200%,甚至更多。在这种情况下,使用副本机制会使 /GB 的存储费用大幅上升;
解决方案
从 Firefly 发行版本开始,Ceph 推出被称为 Erasure Code(纠删码)的数据保护方法;
原理简述
概述流程
在写入数据时,将每个 Object 划分成更小的 Chunk(数据块),每个块称为 Data Chunk(数据块),再用 Coding Chunk(编码块)对它们进行编码,最后将 Data Chunk 与 Coding Chunk 共同存储到 Ceph Cluster 中的不同故障域中,从而保证数据安全;
纠删码原理
Ceph 可以加载多种纠删码算法。最早且最常用的纠删码算法是 Reed-Solomon。纠删码实际上是前向纠错(Forward Error Correction,FEC)码;
FEC 代码将 K 个 chunk(以下称为块)数据进行冗余校验处理,得到 N 个块数据。这 N 个块数据既包含原数据,也包括校验数据。这样就能保证 K 个块中如果有数据丢失,可以通过 N 个块中包含的校验数据进行恢复;
N=K+M,是纠删码概念的核心在公式。具体地说,变量 K 是数据块即原始数量;变量 M 代表防止故障的冗余块的数量;变量 N 是在纠删码之后创建的块的总数。这种方法保证 Ceph 可以访问所有原始数据,可以抵抗任意 M 个故障。例如,当 K=10, N=16 时,Ceph 会将 6 个冗余块添加到 10 个基本块 K 中。在 M=N–K(即 16–10=6)的配置中,Ceph 会将 16 个块分布在 16 个 OSD 中,这样即使 6 个 OSD 掉线,也可以从 10 个块中重建原始文件,以确保不会丢失数据,提高容错能力;
数据写入过程
在纠删码存储池中,Primary OSD 接收所有写操作。纠删码存储池将每个对象存储为 K+M 个块(K 个数据块和 M 个编码块),配置大小为 K+M,以便 Ceph 将每个块存储到一个 OSD 中。Ceph 将块的等级配置为对象的属性。Secondary OSD 负责将对象编码为 K+M 个块,并将其发送给其他 OSD。Secondary OSD 还负责维护放置组日志的权威版本;
首先,创建 5=3+2 的纠删码存储池,所以需要使用 5 个 OSD 来存储数据块,并 M=2 保证在 2 个 OSD 丢失的情况下恢复数据;
然后,当将包含 ABCDEFGHI 的对象 NYAN 写入纠删码存储池时,纠删码算法只需将内容分为 3 个数据块:ABC、DEF、GHI。如果内容长度不是 K(本例中 k=3)的倍数,该算法将补全内容。该算法还会创建两个编码块:编码块 4、编码块 5。Ceph 将每个块存储在一个 OSD 上。这些块具有相同的名称 NYAN,但位于不同 OSD 上。除了对象名称外,还必须记录创建块的顺序作为对象 shard_t 的属性(以用于还原)。例如,编码块 1 包含 ABC,Ceph 将其存储在 OSD5 中;编码块 4 包含 YXY,Ceph 将其存储在 OSD3 中;
在读取数据时,客户端从编码块 1 到编码块 5 中读取对象名称为 NYAN 的对象;
假如 OSD 通知算法编码块 2 和编码块 5 丢失。例如,由于 OSD4 丢失,从 OSD 就无法从 OSD4 中读取编码块 5 中的内容(QGC),并且由于 OSD2 出现严重负载问题,不能读取编码块 2。但是,仍然有 3 个块在线,从 OSD 将读取 3 个块中的内容:块 1 中的 ABC,块 3 中的 GHI 和块 4 中的 YXY,然后重建对象 ABCDEFGHI 的原始内容以及包含 GQC 的块 5 的原始内容;
推荐使用的配比:(1)k=8、m=3;(2)k=8、m=4;(3)k=4、m=2