|
|
一、纠删码原理3 `. P+ [& V1 p% }, s
纠删码(Erasure Coding,EC)是一种编码容错技术,最早是在通信行业解决部分数据在传输中的损耗问题。其基本原理就是把传输的信号分段,加入一定的校验再让各段间发生相互关联,即使在传输过程中丢失部分信号,接收端仍然能通过算法将完整的信息计算出来。在数据存储中,纠删码将数据分割成片段,把冗余数据块扩展和编码,并将其存储在不同的位置,比如磁盘、存储节点或者其他地理位置。如果需要严格区分,实际上按照误码控制的不同功能,可分为检错、纠错和纠删3种类型。
k" }/ ?& n$ G/ ~! E3 }·检错码仅具备识别错码功能而无纠正错码功能。
$ n+ O: S7 k( B1 T/ Y+ w) A5 Y# U, T·纠错码不仅具备识别错码功能,同时具备纠正错码功能。
6 m0 t) s8 s5 |% k" d/ h5 p·纠删码则不仅具备识别错码和纠正错码的功能,而且当错码超过纠正范围时,还可把无法纠错的信息删除。- |* a; z* d: r3 \, P3 g
从纠删码基本的形态看,它是k个数据块+m个校验块的结构,其中k和m值可以按照一定的规则设定,可以用公式:n=k+m来表示。变量k代表原始数据或符号的值。变量m代表故障后添加的提供保护的额外或冗余符号的值。变量n代表纠删码过程后创建的符号的总值。当小于m个存储块(数据块或校验块)损坏的情况下,整体数据块可以通过计算剩余存储块上的数据得到,整体数据不会丢失。
' T+ w; J0 z/ C" F5 W下面以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上面,完成对这个对象的存储操作。如图所示。6 R( n+ f4 I) R- b
下面再看一下如何使用纠删码读取数据,同样还是以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),最终将该结果返回给客户端。整个过程如图所示。
1 z9 |5 w/ g# ?8 g0 Q虽然纠删码能够提供和副本相近的数据可靠性,并降低冗余数据的开销,整体上能提高存储设备的可用空间。但是,纠删码所带来的额外开销主要是大量计算和网络高负载,优点同时伴随缺点。特别是在一个硬盘出现故障的情况下,重建数据非常耗费CPU资源,而且计算一个数据块时需要读出大量数据并通过网络传输。相比副本数据恢复,纠删码数据恢复时给网络带来巨大的负担。因此,使用纠删码对硬件的设备性能是一个较大的考验,这点需要注意。另外,需要注意的是,使用纠删码所建立的存储资源池无法新建RBD块设备。+ W q! X$ |* n2 y0 F
Ceph安装后默认有Default Rule,这个Rule默认是在Host层级进行三副本读写。副本技术带来的优点是高可靠性、优异的读写性能和快速的副本恢复。然而,副本技术带来的成本压力是较高的,特别是三副本数据情景下,每TB数据的成本是硬盘裸容量3倍以上(包括节点CPU和内存均摊开销)。纠删码具备与副本相近的高可用特性,而且降低了冗余数据的开销,同时带来了大量计算和网络高负载。3 x6 R3 C9 N8 X3 c7 ]/ u. I; R) g+ T
Z8 n9 J8 a* H
& P1 X% |3 H2 I$ }2 d0 y; c
二、纠删码实践, g3 K2 o$ k# z; T
纠删码是通过创建erasure类型的Ceph池实现的。这些池是基于一个纠删码配置文件进行创建的,在这个配置文件中定义了纠删码的特征值。现在我们将创建一个纠删码配置文件,并根据这个配置文件创建纠删码池。下面的命令将创建一个名为Ecprofile的纠删码配置文件,它定义的特征值是:k=3和m=2,两者分别表示数据块和校验块的数量。所以,每一个存储在纠删码池中的对象都将分为3(即k)个数据块,和2(即m)个额外添加的校验块,一共有5个块(k+m)。最后,这5(即k+m)个块将分布在不同故障区域中的OSD上。9 G) r) U- ], ~- N6 Z; H
1、创建纠删码配置文件:
6 |. Z+ y0 }; T; [: }9 @. h' F# ceph osd erasure-code-profile set Ecprofilecrush-failure-domain=osd k=3 m=2
& z: X" P- m2 O, [9 x' Y2 f, }2、查看配置文件: Z6 B0 d$ o" `& Y
# ceph osd erasure-code-profile ls
0 m! s; m/ W; z) Q% KEcprofile
~4 B! k& p) D4 Pdefault
$ v3 I6 o# V! M* b# ceph osd erasure-code-profile get Ecprofile
0 Y/ B. h% m' ~$ ~! F9 scrush-device-class=
( d# S u; P& n) l, B. j" y& Hcrush-failure-domain=osd
$ e0 B, r" Q* l6 d0 M6 Acrush-root=default( x0 a1 A: q6 G) x* m
jerasure-per-chunk-alignment=false
" N$ g8 Q8 U9 F$ T& G. S& ?+ Dk=3/ J7 T- @9 f R
m=21 p g1 Q. k" o( i/ |
plugin=jerasure3 K2 F5 v: I3 C6 t8 W0 x
technique=reed_sol_van
! w1 H3 M7 d: w3 q" g# n lw=81 V) _5 Z2 O2 \ {9 z
我们顺便也看Ceph默认的配置文件1 v2 s* h* [. K# c: Y. X4 b
# ceph osd erasure-code-profile get default5 U- k( y% |) Z2 k) h" O
k=2
2 v" {" B3 h' P1 }4 t* e( gm=1" p- s% V! H# h. ~4 F: J2 s: Y
plugin=jerasure" P3 s: N: h; t( i
technique=reed_sol_van$ Y# D2 m8 ?' N+ X% l& ^$ Q
3、基于上一步生成的纠删码配置文件新建一个erasure类型的Ceph池:( g% k% q( s8 R: N& \( v8 j* \, p1 l
# ceph osd pool create testcpool 16 16 erasureEcprofile0 ~6 Q5 S3 F& q9 Q: R
pool 'testcpool' created# ^/ ^, C- F$ Z$ b
4、检查新创建的池的状态,你会发现池的大小是5(k+m),也就是说,erasure大小是5。因此,数据将被写入五个不同的OSD中:
o/ b8 ]. b1 ?1 L+ G4 f8 M6 R# ceph osd dump | grep testcpool' F' O0 @, f, u/ ~/ P5 C
pool 8 'testcpool' erasure size 5 min_size 4crush_rule 3 object_hash rjenkins pg_num 16 pgp_num 16 last_change 231 flagshashpspool stripe_width 12288( ]7 B2 ]5 X( h# ]1 f5 g& W/ I
5、现在我们创建个文件放到纠删码池中。$ E# n' z' Z# w7 R
# echo test > test
) p }& n/ t) `9 j/ n& `' N# ceph osd pool ls
6 F8 h" S* f$ O5 m$ `. @$ ~testcpool9 K5 U! \+ h" M3 u$ R: l/ p5 J( p
# rados put -p testcpool object1 test3 i7 n( _3 t% g' K
# rados -p testcpool ls
; R0 `: F& [7 T! `9 Aobject1. F0 s- }3 y" d" R
6、检查testcpool池中和object1的OSDmap。命令的输出将清晰地显示对象的每个块所在的OSDID。正如步骤1)中说明的那样,object1被分为3(m)个数据块和2(k)个额外的校验块,因此,5个块分别存储在Ceph集群完全不同的OSD上。在这个演示中,object1一直存储在这5个OSD中,它们是osd.5、osd.1、osd.3、osd.2、osd.4。
, C/ B6 i# u6 T) l# ceph osd map testcpool object1; E. q. W. |% G- V# F
osdmap e233 pool 'testcpool' (8) object'object1' -> pg 8.bac5debc (8.c) -> up ([5,1,3,2,4], p5) acting([5,1,3,2,4], p5)0 ^; v1 `0 G. K3 m) q/ P. O" l
: l, l! m4 Y1 K- f* k
三、纠删码测试
; _8 D8 q! A8 z d7 @* r7 z0 W1、我们先来关闭一个osd
$ e) F* M8 }/ n n# r. J# systemctl stop ceph-osd@3( j5 {) K; l7 K9 Z) }: ]8 T2 X3 m* V
停止osd.3,检查testcpool池和object1的OSDmap。你应该注意,这里的osd.3变成NONE了,这意味着osd.3在这个池是不可用的:: {) D- p0 N8 ^5 V" U
# ceph osd map testcpool object1- b5 C" A N9 S0 K7 s6 r
osdmap e235 pool 'testcpool' (8) object'object1' -> pg 8.bac5debc (8.c) -> up ([5,1,NONE,2,4], p5) acting ([5,1,NONE,2,4],p5)
% m( D# J6 d( J3 F: B/ E+ h2、我们再来关闭一个osd1 Z- [) L1 i( [: q
# systemctl stop ceph-osd@5
# i& U+ |& r, q5 E停止osd.5,检查testcpool池和object1的OSDmap。你应该注意,这里的osd.5变成NONE了,这意味着osd.5在这个池是不可用的:
$ d7 K/ X# Z) r5 B2 d- R _7 O# ceph osd map testcpool object1
. U$ U# x: x4 t, o$ ]( d, ~" Wosdmap e237 pool 'testcpool' (8) object'object1' -> pg 8.bac5debc (8.c) -> up ([NONE,1,NONE,2,4], p1) acting([NONE,1,NONE,2,4], p1)) t- r T# s: a, w6 a
3、我们从纠删码池中下载文件
& T# K3 f- }: V% q5 E2 m## rados get -p testcpool object1 /tmp/devops
6 O+ U9 o1 m5 ]
; g& D! F- j: g$ U0 ^5 f6 V* u) s( `. K/ b. B
' g+ J# F5 @; f- b9 Y% z, t4 |
|
|