GlusterFS企业级功能之EC纠删码
《GlusterFS企业级功能之EC纠删码》要点: 在这个数据爆炸的时代,很多行业不得不面临数据快速增长的挑战,为了应对呈爆炸式增长态势的数据量,构建大规模的存储系统成了一种普遍的应用需求.但数据是如此重要,如何保证存储可靠性、数据可用性成了大规模存储系统的难点和要点.数据冗余是保障存储可靠性、数据可用性的最有效手段,传统的冗余机制主要有副本(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,P2}2个校验数据块;当原始数据块D4被更新为D4’时,校验数据块{P1,P2 }也要重新编码更新为{P1’,P2’ };借助解码函数,可根据任意4个数据块(如{D1,P1’})重构出所有的数据块.
图2:纠删码的三种基本操作 纠删码存储的数据恢复过程主要利用编码、解码来恢复丢失的数据.同样以(6,P2}2个校验数据块,然后把所有数据块统一存储. 当原始数据分块D4丢失时,可根据{D1,P1,P2}中任意4个数据块解码计算出原始数据块D4. 图3:纠删码存储的数据分块恢复 当校验数据块P2丢失时,D4,P1 }中任意4个数据块编码计算出校验数据块P2. 图4:纠删码存储的校验分块恢复 在(6,2)RS码为例的纠删码存储中,其冗余度为2,即最多可以同时丢失2块数据块,当丢失的数据块个数大于2时,丢失数据块就不可恢复了. 二、基于EC的开源实现技术现今,基于纠删码的开源实现技术主要有Intel ISA-L、Jerasure等库,以下就来简单介绍一下这两种库: (一)Intel ISA-LIntel ISA-L(Intelligent Storage Acceleration Library),即英特尔智能存储加速库,是英特尔公司开发的一套专门用来加速和优化基于英特尔架构(IntelArchitecture,IA)存储的lib库,可在多种英特尔处理器上运行,能够最大程度提高存储吞吐量,安全性和灵活性,并减少空间使用量.该库还可加速RS码的计算速度,通过使用AES-NI、SSE、AVX、AVX2等指令集来提高计算速度,从而提高编解码性能.同时还可在存储数据可恢复性、数据完整性性、数据安全性以及加速数据压缩等方面提供帮助,并提供了一组高度优化的功能函数,主要有:RAID函数、纠删码函数、CRC(循环冗余检查)函数、缓冲散列(MbH)函数、加密函数压缩函数等. (二)JerasureJerasure是美国田纳西大学Plank教授开发的C/C++纠删码函数库,提供Reed-Solomon和Cauchy Reed-Solomon两种编码算法的实现.Jerasure有1.2和 2.0两个常用版本,Jerasure 2.0为目前的最新版本,可借助intel sse指令集来加速编解码,相比1.2版本有较大的提升.Jerasure库分为5个模块,每个模块包括一个头文件和实现文件. (三)Intel ISA VS JerasureIntel ISA-L库和Jerasure库都能加速RS码的计算速度.其中,ISA-L 库对于加速RS码的计算速度效果更好,是目前业界最佳.ISA-L 之所以速度快,主要有两点,一是由于Intel 谙熟汇编优化之道,ISA-L直接使用汇编代码;二是因为它将整体矩阵运算搬迁到汇编中进行.但这导致了汇编代码的急剧膨胀,令人望而生畏.另外,ISA-L 未对 vandermonde 矩阵做特殊处理,而是直接拼接单位矩阵作为其编码矩阵,因此在某些参数下会出现编码矩阵线性相关的问题. 虽然Jerasure2.0库相较ISA-L 库对于加速RS码的计算速度效果略差,但是Jerasure2.0库在存储应用中仍具有一些ISA-L 库所没有的优势,如Jerasure2.0使用 C 语言封装后的指令,让代码更加的友好.另外Jerasure2.0 不仅仅支持 GF(2^8) 有限域的计算,其还可以进行 GF(2^4) – GF(2^128) 之间的有限域.并且除了 RS 码,还提供了 Cauchy Reed-Solomon code(CRS码)等其他编码方法的支持.且在工业应用之外,其学术价值也非常高,是目前使用最为广泛的编码库之一,开源的Ceph分布式存储系统就是使用Jerasure库作为默认的纠删码库. 三、GlusterFS纠删码卷2011年,Linux系统厂商RedHat红帽以1.36亿美元收购了网红Gluster,然后基于红帽企业的Linux操作系统构建了企业级的RedHat Gluster Storage存储,并在过去的几年里,为其添加了一系列的企业级新功能,如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卷的编码 图7:Dispersed卷的编码 3. Disperse卷的失效数据恢复 图8:Dispersed卷的失效数据恢复 4. Disperse卷的读操作 图9:Dispersed卷的读操作 5. Disperse卷的写操作 图10:Dispersed卷的写操作 (2)部分写 (三)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等几个参数,下面就对几个重要的参数进行简单介绍:
在Gluster 3.9版本中,EC卷又增加了disperse.shd-max-threads、disperse.shd-wait-qlength、disperse.cpu-extensions等三个参数,由于篇幅有限在这里就不做介绍了. 四、EC纠删码卷实践?(一)EC实践总结1、Disperse卷的创建 2、Disperse卷的数据存储 3、Disperse卷的数据恢复 4、Disperse卷的扩展 5、chunk的大小是否与性能有关 6、Disperse卷的均衡 7、Disperse卷的收缩 8、Disperse卷的替换 9、Distributed Disperse卷的数据恢复 10、EC卷的性能总结 (二)EC性能测试1、测试环境 2、测试工具 IOzone,文件系统测试基准工具,可以测试不同操作系统中文件系统的读写性能.主要测试文件系统的write、re-write、read、re-read、random read、random write等性能.注意:在单进程的测试中,测试文件的大小一定要大过内存的大小(最佳值为内存大小的两倍),否则linux会给读写的数据进行缓存,从而造成测试数值不准确. 3、测试方法 # ./iozone -s 16g -r 512k -i 0 -i 1 –t 4. 4、测试结果 5、测试总结 (三)EC配置推荐基于Glusterfs搭建的集群中,创建EC卷推荐以下几种配置: 在底层的配置中,推荐逻辑盘(如/dev/sda)不分区直接格式化为块大小512B的XFS文件系统,且逻辑盘与brick是一一对应的关系;推荐有n个节点,B就等于n,即同一组的Disperse卷配置中,一个brick对应一个节点.比如,三个节点的gluster集群就推荐创建配为(B=3,R=1)的EC卷,每组Disperse卷配置中,一个brick对应一个节点. 五、EC卷的优化方向对于如何优化EC卷的性能主要在于以下几点:一是如何提高编/解码的速度;二是如何提高编码速度的稳定性;三是EC卷参数的可配置;四是如何降低修复的开销. 其中如何提高编/解码的速度是最重要,也是最基础的一点.编/解码的运算速度主要依赖于分布式系统的计算能力以及网络速度,那么可以从三个方面来提高.第一,服务器硬件性能的升级;第二,网络环境的升级;第三,则是使用成熟的库来加速RS码的计算速度,如Intel ISA-L库、Jerasure库等.虽然从这三个方面都能够提高纠删码的编/解码的速度,但其中服务器硬件性能的升级以及网络环境的升级都会增大企业的成本,所以推荐使用第三中方式,即使用成熟的库来提高编/解码的运算速度.其中Jerasure库早已成为开源Ceph分布式存储系统的默认纠删码库,相对于ISA-L库,Jerasure库在这一点上具有一定的先天优势,所以在Gluster存储中推荐使用Jerasure库来加速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卷具有很大的修复开销,这主要是由于RS码本身的特性所导致的,在配置为(D+R)的RS码中修复任何一个数据块时,都需要从磁盘上读取D块的其他数据块,然后在网络上传输,最后使用算法计算恢复.比如在4+2的配置中,丢失任何一个数据块都将必须读取至少4个数据块来修复,在整个修复过程中会占用大量磁盘I/O以及网络流量,并且会使得系统暴露在一种降级的不稳定状态.那么使用较小的D值就能在很大程度上降低修复的开销,还能提高存储的可靠性,但这会降低存储利用率,这就需要在性能和存储空间利用率之间做权衡了. 在EC卷中,无论是读操作、写操作,还是修改操作都需要做大量的计算、通信、下发文件锁等操作.就拿写操作来说,以在配置为(4+2)的EC卷中写一个chunk数据块为例,a.把这个chunk块切分为4个fragment原始数据块;b.读4个原始数据块;c.计算得出2个校验数据块;d.对每个数据块下发文件锁,并添加扩展属性;e.把6个数据块统一写入底层brick中;f.写入成功后,擦除扩展属性.当然,这仅仅只是大概流程,在这其中至少包含10个文件锁、20次通信、5个状态机等等操作.那么是否可以考虑从优化Gluster中关于EC卷的源码这方面来提升EC卷的性能,例如把其中的一些重复操作合并,去除一些不必要的操作,优化算法,从根本上去解决问题,当然这属于对Gluster做二次研发了,还需做具体的调研,在这里就不细说了. EC卷的的核心是以计算换容量,其性能较复制卷略差,但具有更高的存储利用率.那么从实际应用的角度出发,可以这样使用EC卷:创建Tier分层来存储数据,热卷使用复制卷,冷卷使用EC卷.在实际应用中热数据就直接存入复制卷中,当热数据变为冷数据后再把数据迁移到EC卷中,这样就既提供了较高的性能,又保证了较高的存储利用率. 文章来 自微信公众号:运维帮 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |