如何选择纠删码编码引擎



  • 作者介绍:
    徐祥曦,独立开发了多套高性能纠删码/再生码编码引擎
    柳青,华中科技大学博士,研究方向为基于纠删码的分布式存储系统

    前言:
    随着数据的存储呈现出集中化(以分布式存储系统为基础的云存储系统)和移动化(互联网移动终端)的趋势,数据可靠性愈发引起大家的重视。集群所承载的数据量大大上升,但存储介质本身但可靠性却进步很小,这要求我们必须以更加经济有效的方式来保障数据安全。

    副本与纠删码都是通过增加冗余数据的方式来保证数据在发生部分丢失时,原始数据不发生丢失。但相较于副本,纠删码能以低得多的存储空间代价获得相似的可靠性。比如 3 副本下,存储开销为3, 因为同样的数据被存储了三份,而在 10+3(将原始数据分为 10 份,计算 3 份冗余)的纠删码策略下,存储开销为为 1.3。采用纠删码能够极大地减少存储系统的存储开销,减少硬件、运维和管理成本,正是这样巨大的收益驱使各大公司纷纷将纠删码应用于自己的存储系统,比如 Google、Facebook、Azure、EMC 等等国际巨头,在国内以淘宝、华为、七牛云等为代表的公司也在自己的存储系统上应用了纠删码。

    最典型的纠删码算法是里德-所罗门码(Reed-Solomon 码,简称 RS 码)。RS 码最早应用于通信领域,经过数十年的发展,其在存储系统中得到广泛应用,比如光盘中使用 RS 码进行容错,防止光盘上的划痕导致数据不可读;生活中经常使用的二维码就利用了RS 码来提高识别的成功率。近年 RS 码在分布式存储系统中的应用被逐渐推广,一方面是分布式存储系统存储的存储容量和规模增大的需求;另一方面是由于纠删码编码速度在近年得到迅猛提升。随着对高性能纠删码引擎在实际系统中应用需要,也催生了对纠删码在具体系统中实现的各种优化手段。并为相关的决策者带来了困扰——究竟什么样的编码引擎才是高效的呢?

    我们将以这个问题展开对纠删码技术的剖析,帮助企业更全面,深入的了解纠删码在存储系统中的应用并更好地做出技术选型。本系列文章将从纠删码的基本原理开始,随后引出如何判断编码引擎优劣这个问题,接下来将深度分析代码实现,帮助开发者顺利完成定制开发。

    本系列共计上下两篇篇文章:
    (上篇)如何选择纠删码编码引擎
    (下篇)实现高性能纠删码引擎

    本文作为系列首篇,我们将一起探讨纠删码的编码原理与如何选择编码引擎这两个问题。

    一 、纠删码编码原理

    在展开分析之前,我们先来看一看 RS 码是如何工作的。
    下图展示了 3+2(3 份数据,2 份冗余)下对 2 字节长度的数据进行编码与数据修复过程:

    alt text

    为了计算冗余数据,首先我们需要选举出一个合适的编码矩阵。编码矩阵的上部为一个单位矩阵,这样保证了在编码后原始数据依然可以直接读取。通过计算编码矩阵和原始数据的乘积,可以到最终的结果。

    下面介绍解码过程,当 1,2 两块数据丢失,即:

    alt text

    当数据块发生丢失,在编码矩阵中去掉相应行,等式仍然保持成立。这为我们接下来恢复原始数据提供了依据。

    原始数据的修复过程如下:

    alt text

    为了恢复数据,首先我们求剩余编码数据的逆矩阵,等式两边乘上这个逆矩阵仍然保持相等。与此同时,互逆矩阵的乘积为单位矩阵,因此可以被消掉。那么所求得的逆矩阵与剩余块的数据的乘积就是原始数据了。

    数据编码以字节为单位,如果将被编码数据看做一个「数组」,「数组」中每个元素是一个字节,数据按照字节顺序被编码。编码过程是计算编码矩阵中元素和「数组」的乘积过程。为保证乘积的运算结果仍旧在一个字节大小以内(即 0-255),必须应用到有限域[1]。有限域上的算术运算不同于通常实数的运算规则。我们通常事先准备好乘法表,并在算术运算时对每一次乘法进行查表得到计算结果。早期的编码引擎之所以性能不佳,是因为逐字节查表的性能是非常低的。倘若能一次性对多字节进行查表以及相应的吞吐和运算,引擎的工作效率必将大幅度提升。

    许多 CPU 厂商提供了包含更多位数的寄存器(大于 64 位),这类寄存器和相应支持的运算使得用户程序可以同时对大于机器位数的数据进行运算,支持这类寄存器和运算的指令称之为SIMD(Single Instruction Multiple Data)指令集,比如 Intel 支持的 SSE 指令集最大支持 128 bits 的数据运算,AVX2 指令集最大支持 512 bits 的数据运算。它们为我们对一个「数组」数据分别执行相同的操作,提高了数据运算的并行性。目前,市面上所有高性能的纠删码引擎均采用了该项技术以提高编解码性能。

    二、编码引擎评判标准

    我们将从以下几个关键指标来对编码引擎进行分析:
    1、 高编/解码速度;
    2、参数可配置;
    3、代码简洁、稳定;
    4 、降低修复开销等。

    2.1 高编/解码速度

    无须多言,编/解码性能是最基本也是最重要的指标。对于一款性能优异的引擎来说,应该同时满足以下几个指标:
    根据 CPU 的特性自动选择最优的指令集进行加速。上文提到,依赖于SIMD 技术 RS 码编码性能有了大幅度的提高。其中,我们可以利用多种指令集扩展以供加速,引擎应该能够自主发现最优解

    不亚于目前最出色的几款引擎的性能表现(详见第三章 著名引擎对比)

    通过SIMD加速,性能会有大幅度攀升。我们还可以将逐字节查表(下称基本方法)的编码速度与利用 SIMD 技术加速的编码速度做对比,两者应该有数倍的差距

    编/解码速度稳定,对于不同尺寸的数据块会有相近的性能表现。由于系统缓存的影响,当被编码数据的大小和缓存大小相当时,编码应该具有最快的速度。当编码数据的大小大于缓存大小时,内存带宽成为编码速度的瓶颈,文件大小和编码时间呈现近似线性关系。这样,数据编码时间是可预期的,用户的服务质量也是可保障的。在实际中,我们对于大文件进行定长分块,依次编码,分块大小和缓存大小保持一定关系。

    下图展示了在10+4策略下,不同大小的数据块的编码速度变化趋势[2]:

    alt text

    注:

    1. 测试平台:MacBook Pro (Retina, 13-inch, Mid 2014),2.6GHz i5-4278U( 3MB L3 Cache Size), 8 GB 1600 MHz DDR3
    2. 编/解码速度计算公式: 在k+m策略下,每一个数据块的尺寸计作s,编/解码m个数据块的耗时计作t,则 速度 = (k*s)/t
    3. 测试方法:在内存中生成随机数据,运行若干次编/解码,取平均值
    4. 分别执行了avx2指令集, ssse3指令集, 基本方法(base)这三种编码方案
    5. 被编码文件尺寸指,每一个数据块的尺寸与总的数据块个数的乘积,即原始数据的总大小
    6. 作为对比,利用go语言自带的copy函数(copy),对k个数据块进行内存拷贝。copy同样使用了SIMD技术进行加速

    另外,解码速度应该大于或等于编码速度(视丢失的数据块数量而定),下图为10+4策略下修复不同数量的原始数据的速度对比[2]:

    alt text

    注:

    1. 测试平台与上文的编码测试相同
    2. lost data = 丢失数据块数目(个)
    3. 原始数据块每块大小为128KB,总大小为1280KB

    2.2 参数可配置

    一款合理的纠删码引擎必须能做到编码策略在理论范围内可随意切换,这指的是如果要将编码策略进行变化时,仅需从接口传入不同参数而不需要改动引擎本身。这大大降低了后续的开发和维护所需要的精力。一个可配置参数的编码引擎可以根据数据的冷热程度和数据重要程度选择不同的编码系数,比如可靠性要求高的数据可以选择更多冗余。

    2.3 代码简洁、稳定

    为了利用 SIMD 加速我们不得不引入汇编代码或者封装后的 CPU 指令,因此代码形式并不常见。为了增强可读性可将部分逻辑抽离到高级语言,然而会损失部分性能,这其中的利弊需要根据团队的研发实力进行权衡。

    接下来的可维护性也非常重要。首先是接口稳定,不会随着新技术的引入而导致代码大规模重构;另外代码必须经过有合理的测试模块以便在后续的更新中校验新算法。

    比如早先的 SIMD 加速是基于 SSE 指令集扩展来做的,随后 Intel 又推出 AVX 指令集进一步提高了性能,引擎应该能即时跟上硬件进步的步伐。再比方说,再生码[5](可以理解为能减少修复开销的纠删码)是将来发展的趋势,但我们不能因为算法的升级而随意改变引擎的接口。

    2.4 降低修复开销

    纠删码的一大劣势便是修复代价数倍于副本方案。k+m 策略的 RS 码在修复任何一个数据块时,都需要k 份的其他数据从磁盘上读取和在网络上传输。比如 10+4 的方案下,丢失一个数据块将必须读取 10 个块来修复,整个修复过程占用了大量磁盘 I/O 和网络流量,并使得系统暴露在一种降级的不稳定状态。因此,实际系统中应该尽量避免使用过大的 k 值。

    再生码便是为了缓解数据修复开销而被提出的,它能够极大减少节点失效时所需要的吞吐的数据量。然而其复杂度大,一方面降低了编码速度,另外一方面牺牲了传统 RS 码的一些优秀性质,在工程实现上的难度也大于传统纠删码。

    三、著名引擎对比

    目前被应用最广泛并采用了 SIMD 加速的引擎有如下几款:

    1. Intel 出品的 ISA-L[4]
    2. J.S.Plank 教授领导的 Jerasure[5]
    3. klauspost 的个人项目(in Golang)[6]
      这三款引擎的执行效率都非常高,在实现上略有出入,以下是具体分析:

    3.1 ISA-L

    纠删码作为 ISA-L 库所提供的功能之一,其性能应该是目前业界最佳。需要注意的是 Intel 采用的性能测试方法与学术界常用的方式略有出路,其将数据块与冗余块的尺寸之和除以耗时作为速度,而一般的方法是不包含冗余块的。另外,ISA-L 未对 vandermonde 矩阵做特殊处理,而是直接拼接单位矩阵作为其编码矩阵,因此在某些参数下会出现编码矩阵线性相关的问题。好在 ISA-L 提供了cauchy 矩阵作为第二方案。

    ISA-L 之所以速度快,一方面是由于 Intel 谙熟汇编优化之道,其次是因为它将整体矩阵运算搬迁到汇编中进行。但这导致了汇编代码的急剧膨胀,令人望而生畏。

    另外 ISA-L 支持的指令集扩展丰富,下至 SSSE3,上到 AVX512,平台适应性最强。

    3.2 Jerasure2.0

    不同于 ISA-L 直接使用汇编代码,Jerasure2.0 使用 C 语言封装后的指令,这样代码更加的友好。另外 Jerasure2.0 不仅仅支持 GF(2^8) 有限域的计算,其还可以进行 GF(2^4) - GF(2^128) 之间的有限域。并且除了 RS 码,还提供了 Cauchy Reed-Solomon code (CRS 码)等其他编码方法的支持。它在工业应用之外,其学术价值也非常高。目前其是使用最为广泛的编码库之一。

    目前 Jerasure2.0 并不支持 AVX 加速,尽管如此,在仅使用 SSE 的情况下,Jerasure2.0 依然提供了非常高的性能表现。不过其主要作者之一 James S. Plank 教授转了研究方向,另外一位作者 Greenan 博士早已加入工业界。因此后续的维护将是个比较大的问题。

    3.3 klauspost 的 ReedSolomon

    klauspost 利用 Golang 的汇编支持,友好地使用了 SIMD 技术,此款引擎的 SIMD 加速部分是目前我看到的实现中最为简洁的,矩阵运算的部分逻辑被移到了外层高级语言中,加上 Golang 自带的汇编支持,使得汇编代码阅读起来更佳的友好。不过 Go 并没有集成所有指令,部分指令不得不利用 YASM 等汇编编译器将指令编译成字节序列写入汇编文件中。一方面导致了指令的完全不可读,另外一方面这部分代码的语法风格是 Intel 而非 Golang 汇编的 AT&T 风格,平添了迷惑。

    这款引擎比较明显的缺陷有两点:1.对于较大的数据块,编码速度会有巨大的下滑;2.修复速度明显慢于编码速度。

    3.4 编码速度对比

    我在这里选取了Intel ISA-L(图中intel), klauspost 的 ReedSolomon(图中k),以及自研的一款引擎2这三款引擎进行编码效率的对比, 这三款引擎均支持avx2加速。测试结果如下:

    alt text

    注:

    1. 编码速度计算公式,测试方法与上一节相同。其中isa-l默认的速度计算方式与公式有冲突,需要修改为一致
    2. 测试平台 : AWS t2.micro Intel® Xeon® CPU E5-2676 v3 @ 2.40GHz, Memory 1GB
    3. 编码方案:10+4
    4. klauspost的引擎默认开了并发,测试中需要将并发数设置为1

    四、自己实现一款引擎

    可能是由于对开源库后续维护问题的担忧,也有可能是现有方案并不能满足企业对某些特定需求和偏好,很多公司选择了自研引擎。那么如何写出高效的代码呢?在上面的简单介绍中,受限于篇幅我跳过了很多细节。比如 SIMD 技术是如何为纠删码服务的,以及如何利用 CPU Cache 做优化等诸多重要问题。我们会在后续的文章中逐步展开其实现,欢迎大家继续关注。

    备注:

    1. 许以超 马松雅. 代数编码与密码[M]. 北京:高等教育出版社, 2015.
    2. 徐祥曦 Reed-Solomon https://github.com/templexxx/reedsolomon
    3. Alexandros G Dimakis, P Godfrey, Yunnan Wu, Martin J Wainwright, and Kannan Ramchan-dran. Network coding for distributed storage systems. Information Theory, IEEE Transactions on, 56(9):4539–4551, 2010.
    4. Intel ISA-L https://github.com/01org/isa-l
    5. Jerasure http://jerasure.org/
    6. Klauspost Reed-Solomon https://github.com/klauspost/reedsolomon

    想获得更多信息和动态可以关注我的个人公共号: 写个定理

    alt text


登录后回复
 

与 青云QingCloud 社区 的连接断开,我们正在尝试重连,请耐心等待