---------- ec ----------
纠删码是一种将对象持久存储在 Ceph 存储集群中的方法,其中纠删码算法将对象分解为数据块 (k) 和编码块 (m),并将这些块存储在不同的 OSD 中
ceph_ec源码分析: https:
关键词: stripe_width 条带宽度=条带大小 * chunk_size, chunk, chunk_size(cell_size), strip_size 条带大小,
关键数据结构, pg_log: struct pg_log_entry_t
本地回滚条目, 回滚信息: ObjectModDesc mod_desc;
写操作的off和条带宽度对齐: int PrimaryLogPG::do_osd_ops 中
pool.info.requires_aligned_append()
op.extent.offset % pool.info.required_alignment() != 0
EC读写: class PGBackend
EC编码解码: namespace ECUtil
EC事务: ECTransaction
关键函数: int OSDMonitor::prepare_pool_stripe_width -> 准备池条带宽度
logical_offset_is_stripe_aligned
void pg_pool_t::encode
TestErasureCodeLrc.cc
src/test/erasure-code/TestErasureCode.cc
src/tools/erasure-code/ceph-erasure-code-tool.cc
void ECTransaction::generate_transactions
google单元测试: src/test/unit.cc -> int main(int argc, char **argv) -> RUN_ALL_TESTS
b TestErasureCode.cc:90
ErasureCodeTest erasure_code(k, m, chunk_size)
erasure_code.get_chunk_count() -> k+m
erasure_code.encode(want_to_encode, in, &encoded) -> int ErasureCode::encode
encode_prepare(in, *encoded) -> int ErasureCode::encode_prepare
bool buffer::list::rebuild_aligned_size_and_memory
round_up_to
encode_chunks(want_to_encode, encoded)
int ECUtil::encode 是将原始数据按条带宽度进行分割,然后对条带数据编码,得到条带的数据块和校验块。把每个条带化数据块和校验块有序的链接,形成数据块和校验块
int ErasureCode::encode
int ErasureCodeJerasure::encode_chunks
jerasure_encode(&chunks[0], &chunks[k], (*encoded)[0].length()) -> EC编码
void ErasureCodeJerasureReedSolomonVandermonde::jerasure_encode -> jerasure_matrix_encode(k, m, w, matrix, data, coding, blocksize)
jerasure_matrix_dotprod -> JErasure库相关介绍: https:
galois_region_xor
galois_w32_region_xor
...
解码: int ECUtil::decode
int ErasureCodeJerasure::decode_chunks
jerasure_decode(erasures, data, coding, blocksize)
ec, 类 ECBackend 实现了EC的读写操作。ECUtil里定义了编码和解码的函数实现。ECTransaction定了EC的事务
int PrimaryLogPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
case CEPH_OSD_OP_WRITE
requires_aligned_append
t->write(soid, op.extent.offset, op.extent.length, osd_op.indata, op.flags)
默认情况下,Ceph 池是使用“复制”类型创建的。 在复制类型池中,每个对象都被复制到多个磁盘。 这种多重复制是一种称为“复制”的数据保护方法。 相比之下,纠删码池使用与复制不同的数据保护方法。 在纠删码中,数据被分成两种片段:数据块和奇偶校验块。 如果驱动器发生故障或损坏,奇偶校验块将用于重建数据。 在规模上,纠删码相对于复制可以节省空间。 在本文档中,数据块被称为“数据块”,奇偶校验块被称为“编码块”。 纠删码也称为“前向纠错码”。 第一个前向纠错码是由贝尔实验室的 Richard Hamming 于 1950 年开发的。
https:
ceph osd pool create ecpool erasure
echo ABCDEFGHI | rados --pool ecpool put NYAN -
rados --pool ecpool get NYAN -
默认纠删码配置文件可以承受两个 OSD 的重叠丢失而不丢失数据。 此纠删码配置文件相当于大小为 3 的复制池,但具有不同的存储要求:它不需要 3TB 来存储 1TB,而是只需要 2TB 来存储 1TB。 可以使用此命令显示默认配置文件
ceph osd erasure-code-profile get default
k=2
m=2
plugin=jerasure
crush-failure-domain=host
technique=reed_sol_van
默认纠删码池有两个数据块 (K) 和两个编码块 (M)。 默认纠删码池的配置文件是“k=2 m=2”。最简单的纠删码池有两个数据块 (K) 和一个编码块 (M)。 最简单的纠删码池的配置文件是“k=2 m=1”
chunk,块, 当调用编码函数时,它返回彼此大小相同的块。 有两种块:(1)数据块,可以连接起来重建原始对象;(2)编码块,可以用来重建丢失的块
K, 对象被划分为的数据块的数量。 例如,如果 K = 2,则将一个 10KB 的对象分为两个各 5KB 的对象
M, 由编码函数计算的编码块的数量。 M 等于集群中可以丢失的 OSD 数量,而集群不会丢失数据。 例如,如果有两个编码块,则可以丢失两个 OSD 而不会丢失数据
在冗余度(冗余度=实际存储空间/有效存储空间)方面,三副本方式下,每1个数据块都需要额外的2个数据块做副本,冗余度为3/1=3,而在RS-3-2的策略下,每3个数据块只需要额外的2个数据块就能够实现可靠性目标,冗余度为5/3=1.67, 最终,我们通过RS-3-2的方式能够在1.67倍冗余的情况下,实现近似三副本的可靠性
class ECBackend : public PGBackend
int OSDMonitor::prepare_command_pool_set
p.flags |= pg_pool_t::FLAG_EC_OVERWRITES
rados -p ecpool bench 20 write -t 32 -b 4096 --no-cleanup
rbd create rbd/myimage --size 1T --data-pool ec42
设置可覆盖:
ceph osd erasure-code-profile set ec32_nvme \
plugin=jerasure k=2 m=1 technique=reed_sol_van \
crush-root=default crush-failure-domain=host crush-device-class=nvme \
directory=/usr/lib/ceph/erasure-code
ceph osd erasure-code-profile set ec32 \
plugin=jerasure k=2 m=1 technique=reed_sol_van \
crush-root=default crush-failure-domain=host \
directory=/usr/lib/ceph/erasure-code
ceph osd pool create ec_pool 16 erasure ec32
ceph osd pool set ec_pool allow_ec_overwrites true
ceph osd pool application enable ec_pool rbd
rbd create --size 1024 ec_pool/image1
ec:
池上的ec配置, TYPE_ERASURE
osd_types.h
struct pg_pool_t
bool requires_aligned_append() const {
return is_erasure() && !has_flag(FLAG_EC_OVERWRITES);
}
auto& ecp =
get_erasure_code_profile(pool->erasure_code_profile);
auto pm = ecp.find("m");
auto pk = ecp.find("k");
int OSDMonitor::get_erasure_code(const string &erasure_code_profile
/ErasureCodeClay.cc
---------- ec ----------