原理介绍
纠删码(Erasure Coding,EC)是一种编码容错技术,最早是在通信行业解决部分数据在传输中的损耗问题。其基本原理就是把传输的信号分段,加入一定的校验再让各段间发生相互关联,即使在传输过程中丢失部分信号,接收端仍然能通过算法将完整的信息计算出来。在数据存储中,纠删码将数据分割成片段,把冗余数据块扩展和编码,并将其存储在不同的位置,比如磁盘、存储节点或者其他地理位置。如果需要严格区分,实际上按照误码控制的不同功能,可分为检错、纠错和纠删3种类型。
- 检错码仅具备识别错码功能而无纠正错码功能。
- 纠错码不仅具备识别错码功能,同时具备纠正错码功能。
- 纠删码则不仅具备识别错码和纠正错码的功能,而且当错码超过纠正范围时,还可把无法纠错的信息删除。
从纠删码基本的形态看,它是k个数据块+m个校验块的结构,其中k和m值可以按照一定的规则设定,可以用公式:n=k+m来表示。变量k代表原始数据或符号的值。变量m代表故障后添加的提供保护的额外或冗余符号的值。变量n代表纠删码过程后创建的符号的总值。当小于m个存储块(数据块或校验块)损坏的情况下,整体数据块可以通过计算剩余存储块上的数据得到,整体数据不会丢失。
下面以k=2,m=1为例,介绍一下如何以纠删码的形式将一个名称为cat.jpg的对象存放在Ceph中,假定该对象的内容为ABCDEFGH。客户端在将cat.jpg上传到Ceph以后,会在主OSD中调用相应的纠删码算法对数据进行编码计算:将原来的ABCDEFGH拆分成两个分片,对应图11-2中的条带分片1(内容为ABCD)和条带分片2(内容为EFGH),之后再计算出另外一个校验条带分片3(内容为WXYZ)。按照crushmap所指定的规则,将这3个分片随机分布在3个不同的OSD上面,完成对这个对象的存储操作。如图所示。
当然实际存储的过程中,还要经过ceph的pgp尽心归置,然后又pg管理对象内容,实际写入到osd上。
下面再看一下如何使用纠删码读取数据,同样还是以cat.jpg为例。客户端在发起读取cat.jpg请求以后,这个对象所在PG的主OSD会向其他关联的OSD发起读取请求,比如主OSD是图中的OSD1,当请求发送到了OSD2和OSD3,此时刚好OSD2出现故障无法回应请求,导致最终只能获取到OSD1(内容为ABCD)和OSD3(WXYZ)的条带分片,此时OSD1作为主OSD会对OSD1和OSD3的数据分片做纠删码解码操作,计算出OSD2上面的分片内容(即EFGH),之后重新组合出新的cat.jpg内容(ABCDEFGH),最终将该结果返回给客户端。整个过程如图所示。
纠删配置
常用命令
osd erasure-code-profile get <name> get erasure code profile <name>
osd erasure-code-profile ls list all erasure code profiles
osd erasure-code-profile rm <name> remove erasure code profile <name>
osd erasure-code-profile set <name> {<profile> [<profile>...]} {-- create erasure code profile <name> with [<key[=value]> ...] pairs. Add
force} a --force at the end to override an existing profile (VERY DANGEROUS)
ceph osd pool create [pool_name] [pg_num] {pgp_num} erasure {profile} 使用已有的profile创建一个存储池。
在M版本开始,pgp_num可以不指定,默认和pg_num一致。
profiler如果不指定,则使用default
ceph osd pool set [pool_name] allow_ec_overwrites true 设置存储池allow_ec_overwrites属性
查看本地纠删配置文件列表
osd erasure-code-profile ls
输出如下:
default
如果没有手动在集群上创建额外的配置文件,默认只有一个default配置项目。在使用ceph osd pool create命令创建存储池的时候,如果不指定profile,则使用它
创建配置文件
ceph osd erasure-code-profile set ec_profile \
k=3 \
m=2 \
crush-failure-domain=osd \
--force
ceph osd erasure-code-profile set命令可以创建一个新的profile(如果不存在的话),也可以修改已有的profile(如果已经存在),当然修改的时候,需要带上–force参数。
其中crush-failure-domain是故障域,这个参数非常重要。因为我们的是测试环境,只有三台hosts,所以设置的crush-failure-domain为osd。也就是说,数据块K和校验块M会被写到不同的osd上,我们的osd数量要满足大于等于k+m个。如果不满足,创建的存储池的pg状态会一直处于creating+incomplete状态,且无存储池无法读写。
查看profile配置信息
我们可以使用如下命令查看profile的配置信息:
ceph osd erasure-code-profile get ec_profile
输出如下:
crush-device-class=
crush-failure-domain=osd
crush-root=default
jerasure-per-chunk-alignment=false
k=3
m=2
plugin=jerasure
technique=reed_sol_van
w=8
创建存储池
我们使用刚才创建的ec_profile创建一个存储池:
ceph osd pool create china_ec 64 erasure ec_profile
查看存储池信息:
ceph osd dump | grep 'china_ec'
输出如下:
pool 15 'china_ec' erasure size 5 min_size 4 crush_rule 2 object_hash rjenkins pg_num 64 pgp_num 64 autoscale_mode warn last_change 9143 lfor 0/0/9138 flags hashpspool,selfmanaged_snaps stripe_width 12288
从输出信息中,我们可以获取如下信息:
- erasure size:5;也就是3+2,一份数据会被分割成3份,同时计算出2份校验块。
- min_size 4:4;因为我们的M=2,我理解的应该是容许损失2块osd。但实际上是只能损失一个osd,这个说明我们对M的理解还是有问题的
- crush_rule:2;使用的profile的id,对应china_ec;
- pg_num和pgp_num:64;我们使用的M版本,虽然我们在创建的时候,只制定了一个64,但是创建后的pg_num和pgp_num都为64。这可能是新版本的改动,老版本需要指定pg_num和pgp_num。
- flags:hashpspool,selfmanaged_snaps
配置rbd
默认情况下,纠删存储池只能比较好的支持rgw。从L版本开始,纠删存储池支持开启allow_ec_overwrites属性,从而使得纠删存储池可以作为rbd或者cephfs的数据池。支持rbd需要有如下几个条件:
- 版本大于等于L
- 开启allow_ec_overwrites
- bluestore存储引擎
- 纠删存储池不支持omap,需要一个副本存储池存储块设备的元数据等信息。该副本存储池可以初始化为rbd应用
开启allow_ec_overwrites:
ceph osd pool set ec_pool allow_ec_overwrites true
我们事先已经创建了一个叫china_re的三副本存储池,并初始化为rbd应用。我们可以使用如下命令创建对应的块设备:
rbd create --size 10G --data-pool china_ec china_re/test
注意:如果我们想让纠删存储池作为块设备的数据池,我们建议把该纠删池也初始化为rbd应用。这样不会有如下警示:
application not enabled on 1 pool(s)