GlusterFS企业级功能之EC纠删码

Posted 刘爱贵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GlusterFS企业级功能之EC纠删码相关的知识,希望对你有一定的参考价值。

(TaoCloud团队原创  作者:杨阳@TaoCloud)


在这个数据爆炸的时代,很多行业不得不面临数据快速增长的挑战,为了应对呈爆炸式增长态势的数据量,构建大规模的存储系统成了一种普遍的应用需求。但数据是如此重要,如何保证存储可靠性、数据可用性成了大规模存储系统的难点和要点。数据冗余是保障存储可靠性、数据可用性的最有效手段,传统的冗余机制主要有副本(Replication)和纠删编码(Erasure Code,以下简称纠删码或EC)两种方式。

副本是将每个原始数据分块都镜像复制到另一存储介质上,从而保证在原始数据失效后,数据仍然可用并能通过副本数据恢复。在副本机制中,数据的可靠性和副本数是呈正相关,副本数越多,数据可用性越好,可靠性也越高,但也意味着更低的空间利用率以及更高的成本。在大规模存储系统中,节点出现故障并发生失效是一种大概率事件,这也就意味着双副本并不能满足企业对存储可靠性的需求,但三副本的存储开销太大,高达200%,且随着存储规模的增大,对存储系统的开销(如容量空间成本、运营成本等)都将显著增加。

相较于副本机制,纠删码机制具有更高的存储效率,在提供相同存储可靠性的条件下,可以最小化冗余存储开销。纠删码机制在网路环境下,其高存储效率的特性还能能显著降低网络中的数据流量,也就意味着在大规模存储系统中使用纠删码机制能够节约网路带宽和存储空间。所以在大规模存储的应用场景中,纠删码机制成了保证存储可靠性、数据可用性的最佳选择。

一、存储应用中的纠删码
(一)什么是纠删码

纠删码本身是一种编码容错技术,起源于通信传输领域,用来解决通信过程中部分数据在传输过程中丢失的问题。其基本原理是传送端把需要传输的信号分段,然后加入一定的校验并让各信号段之间间产生一定的联系,最后统一把所有信号段向接收端发送;如果在传输过程中有部分信号丢失,接收端仍可以通过算法把完整的信息计算出来,从而保证了两端之间的可靠通信。其原理如下图所示:
 

图1:纠删码的原理图


客户端,把原始数据信息切分为k块source data,然后通过纠删码Encoder生成n块encoded data,最后统一向服务端传输;服务端,只要能够接收到k` >= k块的encoded data,就能够通过纠删码decoder出所有的source data。

(二)纠删码的分类
按照误码控制的不同功能,可分为检错、纠错和纠删三种类型。检错码仅具备识别错码功能而无纠正错码功能;纠错码不仅具备识别错码功能,同时还具备纠正错码功能;纠删码则不仅具备识别错码和纠正错码的功能,而且当错码超过纠正范围时,还可把无法纠错的信息删除。

按照存储单元连接方式的不同,可分为基于高速总线方式的磁盘阵列、基于LAN方式的集群存储和基于WAN/Internet方式的广域网络存储系统。阵列码是一种特殊化的纠删码,其采用高效率的异或运算(XOR),如RAID5、RAID6等。集群存储系统中,如HDFS的HDFS-RAID、PanFS支持RAID-5容错编码、Google的GFSⅡ、微软的WAS等;广域网下,如RACS、DepSky等;开源的集群存储系统中,如GlusterFS的EC卷、ceph纠删码等。

纠删码常见的有里德-所罗门码Reed-Solomen(简称RS)、级联低密度纠删码和数字喷泉码三类。目前在存储行业内的应用中,主要使用的是RS类纠删码,比如光盘存储中使用 RS 码进行容错,防止光盘上的划痕导致数据不可读;生活中经常使用的二维码就利用了RS码来提高识别的成功率。主要原因就是,RS类码是唯一可以满足任意磁盘数目N和校验数据M中丢失M块后能恢复的Maximum Distance Separable(简称MDS)编码,所以下文中主要以RS类码来介绍纠删码在存储应用中的使用原理。

(三)纠删码在存储应用中的使用原理
在大规模存储应用场景中,节点故障、数据失效是一种常态,使用纠删码来保证存储可靠性、数据可用性是目前的最有效方式之一。其原理是将文件数据分割成N个大小相同的原始数据块,然后编码生成M个大小相同的校验数据块(注:原始数据块和校验数据块大小相同),最后将原始数据块和校验数据块分别存储在不同的位置,如不同的磁盘、不同的存储节点等。纠删码的容错能力正是来源于这些校验数据块,在1~M个数据块(注:原始数据或校验都行)损坏的情况下,整体数据仍然可以通过剩余的数据块计算得出,确保了数据仍的高可用性。

纠删码存储的存取过程包含编码、修改、解码三种基本操作。以(6,2)RS码为例,文件划分为4个原始数据块D1,D2,D3,D4,经过编码得到P1,P22个校验数据块;当原始数据块D4被更新为D4’时,校验数据块P1,P2 也要重新编码更新为P1’,P2’ ;借助解码函数,可根据任意4个数据块(如D1,D2,D3,P1’)重构出所有的数据块。

图2:纠删码的三种基本操作


纠删码存储的数据恢复过程主要利用编码、解码来恢复丢失的数据。同样以(6,2)RS码为例,文件划分为4个原始数据块D1,D2,D3,D4,经过编码得到P1,P22个校验数据块,然后把所有数据块统一存储。

当原始数据分块D4丢失时,可根据D1,D2,D3,P1,P2中任意4个数据块解码计算出原始数据块D4。

图3:纠删码存储的数据分块恢复


当校验数据块P2丢失时,可根据D1,D2,D3,D4,P1 中任意4个数据块编码计算出校验数据块P2。

图4:纠删码存储的校验分块恢复


在(6,2)RS码为例的纠删码存储中,其冗余度为2,即最多可以同时丢失2块数据块,当丢失的数据块个数大于2时,丢失数据块就不可恢复了。

二、基于EC的开源实现技术
现今,基于纠删码的开源实现技术主要有Intel ISA-L、Jerasure等库,以下就来简单介绍一下这两种库:

(一)Intel ISA-L
Intel ISA-L(Intelligent Storage Acceleration Library),即英特尔智能存储加速库,是英特尔公司开发的一套专门用来加速和优化基于英特尔架构(IntelArchitecture,IA)存储的lib库,可在多种英特尔处理器上运行,能够最大程度提高存储吞吐量,安全性和灵活性,并减少空间使用量。 ISA-L库可在存储数据可恢复性、数据完整性性、数据安全性以及加速数据压缩等方面提供帮助,并提供了一组高度优化的功能函数,主要有:EC纠删码函数、RAID函数、CRC(Cyclic Redundancy Check)循环冗余检查函数、MBH(Multi Buffer Hash)缓冲散列函数、加密函数、Compression压缩函数等。其中EC纠删码函数可以加速任何以GF(28)为编/解码矩阵的RS类纠删码的计算速度。


(二)Jerasure
Jerasure是美国田纳西大学Plank教授开发的C/C++纠删码函数库,提供Reed-Solomon和Cauchy Reed-Solomon两种编码算法的实现。Jerasure有1.2和 2.0两个常用版本,Jerasure 2.0为目前的最新版本,可借助intel sse指令集来加速编解码,相比1.2版本有较大的提升。 Jerasure库分为5个模块,每个模块包括一个头文件和实现文件。

(1)galois.h/galois.c:提供了Galois Field Arithmetic伽罗华域算术运算。

(2)jerasure.j/jerasure.c:依赖于galois模块,可为绝大部分的纠删码提供核心函数,其中这些核心函数支持基于矩阵的编码与解码、基于位矩阵的编码与解码、位矩阵变换、矩阵转置和位矩阵转置。

(3)reed sol.h/reed sol.c:支持RS编/解码和优化后的RS编码。

(4)cauchy.h/cauchy.c:支持柯西RS编解码和最优柯西RS编码。

(5)liberation.h/liberation.c:支持Liberation RAID-6编码、Blaum-Roth编码和Liber8tion编码。其中,Liberation RAID-6是一种基于二进制矩阵的最低密度MDS编码,其性能在相同参数设置下,较RS编码和柯西RS编码更好。


(三)Intel ISA VS Jerasure
Intel ISA-L库和Jerasure库都能加速RS码的计算速度。其中,ISA-L 库对于加速RS码的计算速度效果更好,是目前业界最佳。ISA-L之所以速度快,主要原因在于Intel 在ISA-L的实现中大量使用了汇编代码,如使用AES-NI、SSE、AVX、AVX2等指令集来提高计算速度、将整体矩阵的运算搬迁到汇编中进行等,虽然这提高了ISA-L的效率性,但大大降低ISA-L代码的可读性和可维护性。ISA-L支持Vandermonde、Cauchy两种编码矩阵,但其中Vandermonde矩阵使用直接拼接单位矩阵的方式作为其编码矩阵,出现了矩阵线性相关等问题。


虽然Jerasure2.0库相较ISA-L 库对于加速RS码的计算速度效果略差,但是Jerasure2.0库在存储应用中仍具有一些ISA-L 库所没有的优势,如Jerasure2.0使用 C 语言封装后的指令,提高了代码的可读性和可维护性,让代码更加友好。另外Jerasure2.0还支持更多有限域的计算,如GF(28)、GF(216)、GF(232)等有限域,并且还支持柯西RS编码、Liberation RAID-6编码、Blaum-Roth编码等其他编码。Jerasure库不但具有极高的学术价值,而且在工业应用中的使用也极为广泛,如在存储应用中开源的Ceph分布式存储系统就是使用Jerasure库作为默认的纠删码库。


三、GlusterFS纠删码卷
2011年,Linux系统厂商RedHat红帽以1.36亿美元收购了网红Gluster,然后基于红帽企业的Linux操作系统构建了企业级的RedHatGlusterStorage存储,并在过去的几年里,为其添加了一系列的企业级新功能,如EC(Erasure Code)纠删码卷、SSD Tier分层、Geo-Replication远程复制等,显著增强了GlusterFS存储的性能、可靠性、灵活性与安全性。

在早期版本的GlusterFS存储中,其中有两种基本卷,Striped卷和Replicated卷。其中Striped卷提供了较高的物理磁盘空间利用率机制,但不提供容错机制,即可靠性较差;Replicated卷提供了容错机制,但对物理磁盘空间利用率较低。那么可不可以结合Striped卷、Replicated卷两者的优点,开发一种具有即能提供容错机制、又能提高物理磁盘空间利用率的卷呢?于是有了EC纠删码卷的出现。在GlusterFS 3.6版本中发布了一种基于Erasure Code所开发的新类型卷Dispersed卷和Distributed Dispersed卷,简称EC卷,类似于RAID5/6。

(一)EC卷的架构
在GlusterFS存储中,EC卷是通过使用系统内存储的信息来重建丢失或损坏的数据,从而进一步加强对数据的保护。下面就简单介绍EC卷的自修复过程:首先客户端检查元数据是否一致;如果不一致,则向服务端发出数据修复请求;服务端接收到请求后则会调用entrylk()和inodelk()两个函数,先是和客户端通信确认,确认后,如果修复准备就绪,就开始对元数据进行修复;元数据修复成功后,下一步就是对数据块的修复了,数据块在修复期间是没有锁的;数据块修复成功后会再次调用inodelk()函数,用于同步元数据(如扩展属性),同步成功后,自修复也就完成了。其架构如下图所示:

图5:架构图


在GlusterFS存储中,有两种卷是基于erasure codes的,分别是Dispersed卷和Distributed Dispersed卷。其核心思想是以计算换容量,和RAID类似,同样突破了单盘容量的限制,且能够通过配置Redundancy(冗余)级别来提高数据的可靠性,也就是说存储系统底层不做RAID,使用EC卷就能提供大容量的存储空间,还能保证较高的存储可靠性。

Dispersed卷可以有任意多个bricks(B),且可配置冗余度redunancy(R),R最小值为1,最大值为(B-1)/2。R的最小值不能为0的原因在于,如果当R的值为0时,卷就不提供容错机制了,其性能还不如直接使用哈希卷,所以限定R最小值为1;R的最大值为(B-1)/2的原因在于,当R的值为B/2时,其存储利用率和replica-2复制卷相同,但其性能就远远不如replica-2复制卷了,所以限定其最大值为(B-1)/2。R最小值、最大值的确定使得B的最小值被确定为3,也就是说创建EC卷至少需要3个brick,才能创建成功。

Dispersed卷提高了存储空间的利用率,其存储利用率计算公式为(B-R)/B,有效存储空间为(B-R)*Brick_size,在理论上存储空间利用率可以达到99.9%。也就是说,能够保证在提供一定容错机制的情况下,最大限度的提高存储利用率。

Dispersed卷提高了存储的可靠性,只要任意大于等于B-R个brick能够正常则数据可正常读写,就能够保证数据是可用的、可恢复的;同时还优化了带宽的使用,且部分文件数据的分片失效引起的降级读写不影响其他文件数据的读写。

Distributed Dispersed 卷可以通过扩展Dispersed 卷生成,即扩展一倍或n倍的bricks(B)。对比于Dispersed卷,其原理相同,但在相同的erasure codeing配置下,具有更好的I/O性能。所以下文中将主要以Dispersed卷来介绍EC卷的原理。

(二)EC卷的原理
1. Disperse卷的机制
Disperse卷中,会把每个读写请求切分为大小相同的Chunk块,而每个Chunk块又被分割成(B-R)个大小为512bytes的Fragment数据分片;然后使用算法Rabin IDA计算生成R个大小为512bytes的Fragment校验分片;最后把(B-R)个数据分片和R个校验分片以条带的方式存储在一起,即分别存储于每个Brick上,从而降低访问热点;其中R个校验分片会以轮询轮的方式存储于卷的每个brick上,用以提高卷的可靠性。(注:Fragment的大小在GlusterFS的源码中是一个宏定义,其大小等于EC_METHOD_WORD_SIZE* EC_GF_BITS=64*8=512 bytes)

Disperse卷中,Chunk的大小可配置,其大小与具体的Redundancy配置有关,其大小等于512*(B-R) bytes。可通过调整Redundancy的配置(注:Redundancy的配置在Disperse卷创建之后就确定,不可修改),来修改Chunk的大小。那么以官方经典的配置B=6,R=2的Disperse卷为例,得出Chunk的大小为(6-2)*512=2048 bytes。

Chunk的大小与性能有关,而性能又与访问模式以及文件大小有关。其性能会随着Chunk的大小改变而改变,用户可以根据具体的应用场景,通过调整Chunk的大小,在存储利用和可靠性之间做均衡选择,从而获得更好的性能。

图6:Dispersed卷的存储机制


2. Disperse卷的编码
Disperse卷使用算法Rabin IDA(Information Dispersal Algorithm)进行编码,其中R(redundancy)个校验数据由(B-R)个原始数据计算得出。


图7:Dispersed卷的编码


3. Disperse卷的失效数据恢复
任意数据/校验块的失效都可用(B-R)个数据/校验块通过解码/编码恢复,数据块通过解码方式恢复,校验块通过编码方式恢复。

图8:Dispersed卷的失效数据恢复


4. Disperse卷的读操作
读操作,每个Chunk都必须从B-R个brick中成功读取B-R个数据/校验分片;尽量读数据块而不是校验块;校验块轮询分布在各个brick上,达到更好的平衡负载。

图9:Dispersed卷的读操作


5. Disperse卷的写操作
(1)普通的写操作
根据(B-R)个原始数据块使用算法IDA计算得出R(redundancy)个校验块,然后再把数据块和校验块以条带的方式一起写入底层所有brick中。

图10:Dispersed卷的写操作


(2)部分写
部分写分为两种情况,一是没有失效的数据块分片,首先将不完整的Chunk将读出来,然后结合新写入数据重新计算校验块,最后再把数据块、校验块统一写入底层brick中;二是有失效的数据块分片,首先利用该Chunk中其他的分片通过编码/解码计算恢复,然后结合新写入数据重新计算校验块,最后再把数据块、校验块统一写入底层brick中。

(三)EC卷的参数介绍
在Gluster3.7版本中,EC卷有disperse.eager-lock、cluster.disperse-self-heal-daemon、cluster.heal-timeout、disperse.background-heals、disperse.heal-wait-qlength以及disperse.read-policy等几个参数,下面就对几个重要的参数进行简单介绍:

disperse.eager-lock:默认值为on,建议把这个参数设置为off。设置为off时,虽然会降低读性能,但当对于文件的操作完成后文件锁能够立即得到释放,从而提升一些操作(如写操作、修复等操作)的性能。
disperse.background-heals:默认值为8,用来控制平行修复时的个数。
disperse.heal-wait-qlength:默认值为128,用来控制等待修复的个数。
disperse.read-policy:默认值为round-robin,用来设置读的策略。
cluster.heal-timeout:默认值为600,用来设置自修复进程检查需要自修复文件的时间间隔。

在Gluster 3.9版本中,EC卷又增加了disperse.shd-max-threads、disperse.shd-wait-qlength、disperse.cpu-extensions等三个参数,由于篇幅有限在这里就不做介绍了。

四、EC纠删码卷实践
(一)EC实践总结

1、Disperse卷的创建
Disperse卷的创建与节点个数无关(节点个数大于等于1),只与bricks(B)、冗余度redunancy(R)相关;其中bricks(B)必须大于等于3,disperse-data 的个数必须要大于等于2,redunancy(R)的值最小为1,最大为(B-1)/2、必须小于bricks(B)的一半且值是不能改变的。

2、Disperse卷的数据存储
disperse卷的单个底层brick中不具有完整数据,需整合多个brick上的数据片段才能看到完整的文件数据;底层brick中存储的不是原始数据;数据块和校验块是存储在一起的。

3、Disperse卷的数据恢复
在配置bricks(B)为3,冗余度redunancy(R)为1的disperse卷中,任意挂掉一个brick后,数据都能够恢复,且不影响正常访问;在修复大文件数据时,需要同步访问来触发才能修复数据;修复小文件数据,则不需要;手动删除底层brick中的数据,也能够实现修复。

4、Disperse卷的扩展
三个brick的disperse卷不能同时扩展一个或两个brick,只能同时扩展3n(n>=1)个brick,即disperse卷不能任意扩展卷,只能同时扩展n*B(n>=1)个brick;Distributed Dispersed 卷可以通过扩展Dispersed 卷生成;Dispersed 卷可在在线扩展,且扩展过程中不影响数据的访问。

5、chunk的大小是否与性能有关
disperse卷的性能会随着chunk的大小改变而改变,用户可以根据需求改变chunk的大小来调整disperse卷的性能。可通过调整EC配置,来修改Chunk的大小。(注:冗余度Redundancy在Disperse卷创建之后就确定,且不可修改。)

6、Disperse卷的均衡
disperse卷在扩展卷时不会自动均衡卷,需要手动均衡卷;均衡时,小文件直接进行迁移均衡,大文件则是先建立黏着位链接,然后再进行数据迁移均衡。

7、Disperse卷的收缩
disperse卷在收缩卷时,不能任意收缩,只能同时收缩n*B(n>=1)个brick;必须先迁移数据然后才能删除相应的brick。

8、Disperse卷的替换
disperse卷在替换brick时,替换的brick不能是卷内部的brick,也不能是其他卷里面的brick;目录也能够替换;替换正常运行的brick是通过计算所有节点中brick的数据来进行替换的;替换过不正常运行的brick是通过计算其他节点中正常运行的brick中数据来进行替换的;且替换过程中不影响卷的正常访问。

9、Distributed Disperse卷的数据恢复
在配置B为6、R为2的Distributed Disperse卷中,最多只能同时挂掉不同组中的2个brick;写文件时,文件的数据块和校验块都只会存储在一个组中,不会交叉存储;同时具有Distributed卷和Disperse卷的特性,其中Disperse卷作为Distributed卷的子卷。

10、EC卷的性能总结
相同EC配置下Distributed-Disperse卷比Disperse卷具有更好的IO性能;相同disperse-data个数的Disperse卷的性能相近;相同冗余配置的EC卷比复制卷具有更大的空间利用率,但读写性能均比复制卷略差;相对于分布式复制卷,Distributed-Disperse卷的优点是具有较高的磁盘利用率和容错性,但是其IOPS性能下降较多。
在配置为1 x (2+1)的disperse卷中任意挂掉一个brick后,不影响数据的正常访问;数据的修复是通过计算其他两个节点中的brick来修复的;在修复100G数据时,替换brick用时约2.2秒,但是发现替换成功后新的brick中并没有数据,需要同步访问来触发才能修复数据;修复100M 数据,则不需要同步访问来触发修复;EC卷的稳定性良好,测试过程无报警。

(二)EC性能测试
1、测试环境


2、测试工具
IOzone,文件系统测试基准工具,可以测试不同操作系统中文件系统的读写性能。主要测试文件系统的write、re-write、read、re-read、random read、random write等性能。注意:在单进程的测试中,测试文件的大小一定要大过内存的大小(最佳值为内存大小的两倍),否则linux会给读写的数据进行缓存,从而造成测试数值不准确。

3、测试方法
搭建3个节点的glusterfs集群,创建6x(2+1)的Distributed Dispersed卷,启动卷。在每个节点使用Gluster原生协议本地挂载卷,然后分别在每个节点中使用测试工具iozone,测试进程数为4、块大小为512KB、文件大小为16GB时,EC卷的读写性能,测试命令为# ./iozone -s 16g -r 512k -i 0 -i 1 –t 4。

4、测试结果

5、测试总结
在配置为6x(2+1)的Distributed-Disperse卷测试中,无论是写性能,还是读性能,都达到了1GB/s,特别是写性能更是高达1.5GB/s。由此得出,EC卷是可以满足企业对于性能的一般需求的,是可以在实际环境中使用的。

(三)EC配置推荐
基于Glusterfs搭建的集群中,创建EC卷推荐以下几种配置:
a. 冗余度为1时,推荐创建配置为(2+1)的EC卷;
b. 冗余度为2时,推荐创建配置为(4 +2)的EC卷;
c. 冗余度为3时,推荐创建配置为(8 +3)的EC卷;
d. 冗余度为4时,推荐创建配置为(8 + 4)的EC卷。
由于在相同的EC配置下,Distributed Disperse卷比Disperse卷具有更好的IO性能,所以推荐在硬盘数量足够的情况下创建Distributed Disperse卷。

在底层的配置中,推荐逻辑盘(如/dev/sda)不分区直接格式化为块大小512B的XFS文件系统,且逻辑盘与brick是一一对应的关系;推荐有n个节点,B就等于n,即同一组的Disperse卷配置中,一个brick对应一个节点。比如,三个节点的gluster集群就推荐创建配为(B=3,R=1)的EC卷,每组Disperse卷配置中,一个brick对应一个节点。


五、EC卷的优化方向
对于EC卷的优化可以从三个方面来考虑,一是EC卷性能方面的优化;二是EC卷功能方面的优化;三是EC卷使用方面的优化。

(一)EC卷性能方面的优化
EC卷的核心是以计算换容量,以时间换空间,以一定的性能损失换取更高的存储利用率,并且保证一定的存储可靠性。那么如何优化EC卷的性能就在于如何减小这部分性能损失,而这部分性能损失由主要来自于编/解码计算的开销以及大量流程性操作(如通信,下发文件锁等操作)的开销。


1、如何减少EC卷编/解码的开销
如何减少EC卷编/解码的开销在于如何提高编/解码的速度,而编/解码的速度主要依赖于分布式系统的计算能力以及网络速度,那么可以从三个方面来提高。第一,服务器硬件性能的升级;第二,网络环境的升级;第三,则是使用成熟的库来加速RS码的计算速度,如Intel ISA-L库、Jerasure库等。虽然从这三个方面都能够提高纠删码的编/解码的速度,但其中服务器硬件性能的升级以及网络环境的升级都会增大企业的成本,所以推荐使用第三中方式,即使用成熟的库来提高编/解码的运算速度。其中Jerasure库早已成为开源Ceph分布式存储系统的默认纠删码库,相对于ISA-L库,Jerasure库在这一点上具有一定的先天优势,所以在Gluster存储中推荐使用Jerasure库来加速EC卷的编/解码速度。除了以上几点外,还可以从分布式集群这一特性入手,分布式集群存储中单一节点的计算能力不算很好,但如果能让集群中每个节点协同完成编/解码的计算,就能够拥有足够的计算能力,集群中节点越多,集群的计算能力越强,编/解码的运算速度也就越快,相应的EC卷性能也就越好。


2、如何减少流程性操作的开销
在现今的硬件环境中,CPU的计算能力、存储设备的IOPS、I/O吞吐量、网络带宽等都能完全满足EC卷编/解码对于计算能力的需求,《纠删码存储集群系统设计与优化》一书中提到“经对纠删码存储集群下的访问开销进行分析,发现编/解码计算的开销一般低于总开销的5%,绝大部分开销是由网络传输和磁盘访问引起的”,在也就是说对于EC卷性能的优化主要在于减少流程性操作的开销。


在EC卷中,无论是读操作、写操作,还是修改操作都包含大量的计算、通信、下发文件锁等流程性操作。就拿写操作来说,以在配置为(4+2)的EC卷中写一个chunk数据块为例,a.把这个chunk块切分为4个fragment原始数据块;b.读4个原始数据块;c.计算得出2个校验数据块;d.对每个数据块下发文件锁,并添加扩展属性;e.把6个数据块统一写入底层brick中;f.写入成功后,擦除扩展属性。当然,这仅仅只是大概流程,在这其中至少包含10个文件锁、20次通信、5个状态机等等操作。在EC卷中,数据修复和部分写两个操作的流程性开销更是巨大,严重影响EC卷的性能,把这两个操作的开销降低了,EC卷的性能自然而然也就有了保障。


EC卷的部分写操作开销巨大,这主要是由于相较于普通的写操作更为繁琐,需要先将不完整的Chunk将读出来,然后结合新写入数据重新计算校验块,最后再把数据块、校验块统一写入底层brick中。这就涉及到读操作、写操作,还有修改操作(修改校验块),其中所包含的流程性操作更是多如牛毛,当然开销巨大。在“PARIX: Speculative Partial Writes in Erasure-Coded Systems”一文中提到关于部分写优化的设计,很是具有借鉴意义,其设计被称为PBS,可以提供强一致性保障。原理是,在整个EC组的全量写操作中直接计算出校验数据,并将其写入校验块,同时在变更日志中记录一个特殊操作I,表示将I之前的变更记录取消掉,因为最新的数据已经直接写到校验块内了。


EC卷的修复操作更是开销巨大,这主要是由于RS 码本身的特性所导致的。在配置为(D+R)的RS码中修复任何一个数据块时,都需要从磁盘上读取D块的其他数据块,然后在网络上传输,最后使用算法计算恢复,这其中更是包含大量的流程性操作,使得性能极低。比如在4+2 的配置中,丢失任何一个数据块都将必须读取至少4个数据块来修复,在整个修复过程中会占用大量磁盘 I/O 以及网络流量,并且会使得系统暴露在一种降级的不稳定状态。那么使用较小的D值就能在很大程度上降低修复的开销,还能提高存储的可靠性,但这会降低存储利用率,这就需要在性能和存储空间利用率之间做权衡了。


针对EC卷流程性的开销是否可以考虑从优化Gluster中关于EC卷的源码这方面来提升EC卷的性能,例如把其中的一些重复操作合并,去除一些不必要的操作,优化算法,从根本上去解决问题,当然这属于对Gluster做二次研发了,还需做具体的调研,在这里就不细说了。

(二)EC卷功能方面的优化
EC卷功能方面的优化主要在于实现EC卷参数的可配置性,如编码策略的参数、读策略的参数、修复策略的参数、冗余度配置策略的参数、日志的参数等,不同的参数配置在不同的环境中可以提供更好的性能,实现参数的可配置性可以提高EC卷使用的灵活度,而且参数的可配置性还可以降低后续开发以及维护的开销。


在Gluster存储中, EC卷的性能会随着chunk的大小改变而改变,那么实现chunk大小的参数可配置就显得尤为必要了。实践中,得知chunk的大小等于Fragment_size*(B-R),但其中R的大小在Disperse卷创建之后就确定,且不可修改;而Fragment_size在GlusterFS的源码中又是一个宏定义,其大小等于EC_METHOD_WORD_SIZE* EC_GF_BITS=64*8=512 bytes,这也就是说chunk的大小在disperse卷创建成功后就不可修改,而这极大降低了EC卷在实际应用中的灵活度,例如根据数据的冷热程度和数据重要程度选择不同冗余配置、根据存储文件的大小调整底层块大小从而提高性能等。

(三)EC卷使用方面的优化
EC卷的的核心是以计算换容量,其性能较复制卷略差,但具有更高的存储利用率。那么从实际应用的角度出发,可以这样使用EC卷:创建Tier分层来存储数据,热卷使用复制卷,冷卷使用EC卷。在实际应用中热数据就直接存入复制卷中,当热数据变为冷数据后再把数据迁移到EC卷中,这样就既提供了较高的性能,又保证了较高的存储利用率。


参考文献
1. Ramon Selga, Xavier Hernandez.Disperse_Xlator_Ramon_Datalab.pdf

2. Anuradha Talur.Performance Improvements in Glusterfs AFR and EC.pdf

3. Anna.Glusterfs文件系统剖析-Luna.pdf

4. 纠删码原理及应用.pdf

5. erasure-codes-and-storage-tiers-on-gluster-26-1024.pdf

6. st-gluster-storage-datasheet-inc0267276-v4-0615rm-a4-zh.pdf

7. Red_Hat_Storage-3.1-Administration_Guide-en-US.pdf

8. Red_Hat_Storage-3.1-Console_Administration_Guide-en-US.pdf

9. James S. Plank*, Kevin M. Greenan.Jerasure: A Library in C Facilitating Erasure Coding for Storage Applications

10. Intel ISA-L

11. 黄健忠,曹强等.纠删码存储集群系统设计与优化.科学出版社.2016.1

12. 王凯,贾思懿等.基于IntelISA-L的RS-RAID系统的研究与实现. 计算机工程与应用.2016(15)

13. 朱云锋.分布式存储系统中基于纠删码的容错技术研究

14. 徐祥曦,柳青.如何选择纠删码编码引擎|纠删码技术详解

15. Steinwurf. Performance and Feature Comparison of Erasure Correcting Coding Software Libraries

16. Huiba Li, Yiming Zhang, Zhiming Zhang, Shengyun Liu.PARIX: Speculative Partial Writes in Erasure-Coded Systems

以上是关于GlusterFS企业级功能之EC纠删码的主要内容,如果未能解决你的问题,请参考以下文章

HDFS3.X 系列的 EC 纠删码策略有个安全隐患 HDFS-16420,极端情况下会造成数据丢失

分布式系统下的纠删码技术 -- Erasure Code (EC)

分布式系统下的纠删码技术 -- Erasure Code (EC)

分布式_minio_纠删码

HDFS纠删码

HDFS EC:将纠删码技术融入HDFS