购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

第4章
七星北斗
——大话/详解七种RAID

第3章介绍了磁盘的内部原理、构造以及外部的接口系统。但一块磁盘的容量是有限的,速度也是有限的。对一些应用来说,可能需要上百吉字节(GB)甚至几太字节(TB)大小的分区来存放数据。目前的磁盘单块容量最多能到1TB,这对于现代应用程序来说远远不够。

那么必须要制造单盘容量更大的硬盘么?为解决这个问题,人们发明了RAID技术,即Redundant Array of Independent Disks技术,中文意思是由独立的磁盘组成的具有冗余特性的阵列。既然是阵列,那一定需要很多磁盘来组成;既然是具有冗余特性的,那一定可以允许某块磁盘损坏之后,数据仍然可用。下面我们就来看一下RAID是怎样炼成的。

4.1 大话七种RAID武器

话说几千年前,有位双刀大侠,左右手各拿一把大刀。开始的时候,他总是单独使用每把刀,要么用左手刀,要么用右手刀,但是总被人打败,郁闷至极,于是苦心悟道,静心修炼。他逐渐摸索出一套刀法,自称“合一刀法”,即双刀并用。外人看不见他的第二把刀,只能看到他拿着一把刀。他把两把刀的威力,合二为一,成为一把大刀!

而这种双刀合一的刀法,又可以分为两条路子。一条是常规路子,即这把合二为一的大刀,其实每出一招只有原来一把刀的威力,但是后劲更足了。一把刀顶不起来的时候,可以第二把刀上阵。对于敌人来说,还是只看见一把大刀。另一条是野路子,野路子往往效果很好,每出一招总是具有两把刀的威力之和,而且也具有两把刀的后劲!他实现这个野路子的方法,便是界内早有的思想——分而治之!也就是说他把一把刀又分成了很多细小的元素,每次出招时把两把刀的元素组合起来,所以不但威力大了,后劲也足了!

不过大侠的这个刀法有个致命的弱点,就是双刀息息相关。一旦其中一把刀有所损坏,另一把刀相应的地方也跟着损坏。如果一把刀完全失去效力,那么另一把刀也跟着失效。

双刀大侠一直到临终也没有收一个徒弟,不是因为他武艺不精,而是因为他的合一刀法在当时被认为是野路子,歪门邪路的功夫,所以郁闷一生。临终时他用尽自己最后一点力气在纸上写下了4句诗后,抱憾而终!

刀于我手不为刀,

横分竖割成龙绦。

化作神龙游天际,

龙在我心任逍遥!

这就是后世流传的“合一刀谱”!俗称“龙谱”。

世上最高的刀法在心中,而不是手上!双刀大侠练就的是一门“浩瀚”绝学,一招一式都是铺天盖地,势不可挡!

几百年后,七星大侠在修炼了磁盘大挪移神功和龙谱之后的某一天,他突然两眼发愣:“我悟到了!”然后奋笔疾书,成就了“七星北斗阵”这个空前绝后的阵式!RAID 0阵式就是这个阵式的第一个阵式!下面来看看这个阵式的绝妙之处吧!

4.1.1 RAID 0阵式

首先,这位七星大侠一定是对磁盘大挪移神功有很高的造诣,因为他熟知每块磁盘上面的磁性区域的构造,包括磁道、磁头、扇区和柱面等,这些口诀心法已经烂熟于心。在他看来,盘片就像一个蜂窝,上面的每一个孔都是一个扇区,可以说他已经参透了磁盘。其次,七星大侠一定是对合一刀法的精髓有很深的领悟,即他能领会双刀大侠那4句诗的含义,特别是第二句给了他很大的启发!“横分竖割成龙绦”,暗示着双刀大侠把他的刀在心中分割成了横条带和竖条带,所以叫“横分竖割”。分割完毕之后,双刀大侠把这些分割后所谓的“绦”,即细条带,在心中组合起来形成一条虚拟的“龙”,然后用龙来当作武器,即“龙在我心任逍遥”。

这显然给了七星大侠很大的启发,何不把几块磁盘也给“横分竖割”,然后组成“龙”呢?对,就这么干!七星大侠卖血换来两块磁盘,找了个破庙,在后面搭了个草堆,成天摆弄他那两块用血换来的磁盘。白天出去要饭,晚上回来潜心钻研!他首先决定把两块磁盘都分割成条带,形成“绦”,可是该怎么分好呢?合一刀法的思想主要有两条路;一条是懒人做法,不想动脑子,即威力小、后劲足那种;另一种是需要动脑子算的,即威力足、后劲也足那种。

第一种怎么实现呢?七星大侠冥思苦想,却发现被误导了。因为第一种根本不需要做“绦”。双刀大侠的诗只是描述了威力巨大的第二种路子。所以三下五除二,七星大侠写出了RAID 0阵式中的第一个套路:累加式。也就是说,磁盘还是那些磁盘,什么都不动,也不用“横分竖割”。数据来了,先往第一块磁盘上写。等写满之后,再往第二块上写。然后将这两块磁盘在心中组成一条龙,这就符合了合一刀法的思想。只不过这条龙威力比较弱,因为每次IO只用到了一块磁盘,另一块磁盘没有动作。但是这条龙的后劲,比单个磁盘足了,因为容量相对一块磁盘来说,增大了。

第一套路子实现了,可第二套路子就难了。其实磁盘已经被分割了,扇区不就是被分割的么?但是一个扇区只有512B大小,这不符合合一刀法。因为合一刀法中是“绦”而不是“粒”,分割成粒的话,不仅开销太大,而且组合起来也很困难。所以七星大侠决定完全照搬合一刀法的思想,但是又不能丢弃磁盘已经分割好的扇区,所以七星绞尽脑汁想出这么一个办法,如图4-1和图4-2所示。

图4-1 正常的4块硬盘

图4-2 被分割的4块硬盘

图4-1所示的是4块普通硬盘,其上布满了扇区。扇区是实实在在存在于盘片上的,具有自己的格式。图4-2所示的是引入分割思想之后的硬盘。由于许多文件系统或者卷管理软件都使用块而不是扇区作为基本存储单元,所以图4-2中也使用由4个扇区组成的块作为基本单元。不同磁盘的相同偏移处的块组合成Stripe,也就是条带。

块的编号也是以横向条带方向开始一条一条的向下。这样,对于一个全新的文件系统和RAID 0磁盘组,如果有大块数据写入时,则数据在很大几率上可以以条带为单位写入。也就是说数据被分成多块写入4个硬盘,而不是单硬盘系统中的顺序写入一个硬盘,这就大大提高了速度。图4-3所示的为多块磁盘组成的逻辑磁盘示意图。

图4-3 心中之龙

提示: 磁盘上实实在在存在的只有扇区结构,Stripe并不是一个实实在在的结构,它只是由程序根据算法公式现套现用的。就像戴了一副有格子的眼镜看一张白纸,那么会认为这张白纸被格式化了,其实并没有。另外,条带化之后的多块硬盘,数据是被并行写入所有磁盘的,也就是多管齐下,而不是横向写满一个条带,再写下一个条带。

七星大侠就这样埋头苦苦思考了整整1年,基于合一刀法的横分竖割的思想,完成了“七星北斗阵”的第一个阵式——RAID 0阵式。

4.1.2 RAID 1阵式

花开七朵,各表其一。话说七星在完成RAID 0阵式之后,并没有沾沾自喜,而总是想在合一刀法上有所创新。

提示: RAID 0阵式纵然威力无比,但弱点也很明显:一旦其中一块磁盘废掉,整个阵式将会被轻易攻破。因为每次出招靠的就是“合一”,如果任意一块坏掉,也就没有“合”的意义了。也就是说,数据被我在心中分割,本来老老实实写到一块盘就完事了,可为了追求威力,非要并发写盘,第一、三、五、……块数据写到了1号盘,第二、四、六、……块数据写到了2号盘。但是对于外界来说,会认为是把数据都写到了我心中的一块虚拟盘上。这样不坏则已,一旦其中任何一块磁盘损坏,就会数据全毁,因为数据是被分割开存放在所有磁盘上的。不行,太不保险了。为了追求威力,冒的险太大,要想个稳妥的办法。

于是七星再次冥思苦想,终于创出了RAID 1阵式!

这话要说到800年前,有位“独行侠”,心独身独终日孤单一人。据称他每次出招从来不用双手,总是单手打出单掌,练就了一门“独孤影子掌”。虽说此掌法威力不高,但是自有其妙处。每当他敌不过他人,单掌被击溃的时候,就会立即换用另一只从来都没用过的掌继续出招。这一绝学往往令自以为已经占了上风的敌人在还没有回过神来的情况下,就被打个落花流水!不但他的掌法绝妙,就连他的身法都达到了炉火纯青的地步。他能修炼出一个影子,这个影子平时总是跟随着他,他做什么,影子就做什么。一旦真身损毁,其影子便代替他的真身来动作。这位独行侠遗留的“孤独影子掌”秘笈如下:

心朦胧,掌朦胧。

掌由独心生。

身朦胧,影朦胧。

身影心相同。

花朦胧,夜朦胧。

独饮赏月容。

灯朦胧,人朦胧。

此景何时休?

独行侠的这段诗句不难理解,孤独给了他灵感,身独心也独,如此练就的功夫,也是独孤残影。最后一句说出了大侠的无奈,其实他也不想孤独,但是没人能理解他。

七星大侠领悟了独行侠的苦衷,感受了他的心境。独行侠练就的是一门“无奈”绝学,处处体现着凄惨与潦迫。只有残了,才能重获新生。一只掌断了,另一只掌才能接替,这是何等凄惨?简直凄惨至极!不过往往孤独凄苦的人都很注意自保,虽然招式的威力是最小的,但是这门学问是武林中用于自保的最佳选择。

七星大侠没有理由不选择这门自保神功来解决他在RAID 0阵式中的破绽,也就是安全问题。毫无疑问,RAID 0是强大的,但是也是脆弱的,一点点挫折就足以让RAID 0解体。

七星大侠决定完全抛弃RAID 0的思想,采用独行侠的思想。将两块磁盘中的一块用于正常使用,另一块用作正常使用磁盘的影子。影子总是跟随主人,主人做什么,影子就做什么。工作盘写了一个数据,影子盘在相同位置也写上了数据。读数据的时候,因为数据有两份,可以在工作盘读,也可以到影子盘读,所以增加了并发性。即修炼这个阵式的人,可以同时应付两个敌人的挑衅,自身应付一个,影子应付一个,这无疑是很高明的!

但是应付一个敌人的时候,不像RAID 0阵式那样可以同时使用多块磁盘,只能使用一块磁盘。当其中一块磁盘坏掉,或者其中一块磁盘上某个区域坏掉,那么对应影子盘或者影子盘上对应的位置便会立即接替工作盘,敌人看不出变化。可能独行侠一生都没有遇到同时和两个对手过招的情况,所以在他的秘笈中,并没有体现“并发读”这个功能,只体现了安全自保。

然而七星并没有全面抛弃双刀大侠的思想,而是保留了双刀的精华,即“横分竖割”的基本思想,抛弃了他的算法,即鲁莽而不计后果的并发往各个磁盘上写数据的方法。所谓算法,也即指大侠对付敌人招数的时候,在心中盘算的过程。心算的速度远远快于出招的速度,所以心算引发的延时并不会影响出招。现在江湖人士也大多都是精于钻研算法,而只有制造兵器的铁匠才去钻研如何用料,考虑如何才能减轻兵器重量而不影响兵器的硬度和耐磨度等。

可以说,兵器的材质、设计加上大侠们精心的算法才形成了江湖上形形色色的功夫秘笈!而材质在很大程度上发展是很慢的,想有突破非常困难。但是算法就不同了,大侠可以研究出各种使用兵器的方法,将兵器用得神乎其神!磁盘的转速、磁密度、电路等,虽然一直在提升,但是终究太慢。所以出现了以七星大侠为代表的算法派,他们苦研算法,用来提高磁盘的整体性能。假想某天一旦某个铁匠造出了屠龙刀、倚天剑这般的神器,我想七星这等大侠也就无用武之处了。可惜这两把神器已经在自相残杀中玉石俱焚了。

七星大侠最后给这个阵式起名叫做“RAID 1”。图4-4显示了RAID 1组成的逻辑磁盘。

图4-4 RAID 1示意图

但是七星也深深认识到,这个RAID 1阵式还是有两个大弱点。

在修炼的时候,速度会稍慢,因为每次修炼,除了练真身之外,还要练影子。不然影子不会,出招的时候影子就无法使用。这会对实际使用有一定影响,数据写到工作盘上,也必须写到影子盘上一份。

虽然自己有个影子,但是影子没有给真身增加后劲。真身累了,影子也会被拖累。不管修炼了几个影子,整体的耐力和体力只等于其中一个的体力耐力,也就是真身的体力和耐力。整体的体力和耐力都被限制在体力耐力最小的影子盘或者真身上。也就是说RAID 1提供的最大容量等于所有组成RAID 1的磁盘中容量最小的一块,剩余容量不被使用,RAID 1磁盘组的写性能等于所有磁盘中性能最低的那块磁盘的写性能。

七星看了看RAID 0,又看了看RAID 1,一个鲁莽急躁但威力无比,一个独孤残苦自嘲自保。矣!呜呼哉!!七星心想,我怎么走了两个极端呢?不妥,不妥,二者皆不合我意!于是,七星大侠又开始了苦心钻研,这一下就是2年!

4.1.3 RAID 2阵式

史话: 话说明末清初时期,社会动荡,英雄辈出。有这么一位英雄,号称“优雅剑侠”,他持双手剑,得益于流传甚广的合一刀法,并加入了自己的招式,修炼成了一套“合一优雅剑法”。剑侠深知合一刀法的鲁莽招式,虽然威力巨大,但必会酿成大祸。所以他潜心研究,终于找到一种办法,可以避免合一的鲁莽造成的不可挽回的祸患。他分析过,合一之所以鲁莽就是因为他没有备份措施,兵器有任何一点损坏都会一损俱损。那么是不是可以找一种方法,对兵器上的每个条带都做一个备份,就像当年独行侠那样?但是又不能一个对一个,那就和独行侠无异了。

剑侠的脑子很好用,他从小精于算术,有常人不及之算术功夫。如今他终于发挥出他的算术技能了,他先找来一张纸,然后把他的两把剑和这张纸,并排摆在地上,然后对剑和纸进行横分竖割,然后一一对照,将第一把剑的第一格写上一个1,然后在第二把剑的相同位置上写上一个0,然后在纸的对应位置上算出前二者的和,即1+0=1。然后剑侠设想,一旦第一把剑被损坏,现在只剩第二把剑和那张记满数字的纸,剑侠恍然大悟:原来如此精妙!

为什么呢?虽然第一把剑损坏,但是此时仍然可以出招,因为第一把剑上的数字可以用纸上对应位置的数字,减去第二把剑对应位置上的数据!也就是1-0=1,就可以得出第一把剑上已经丢失的数字!而在敌人看来,仍旧是手持一把大剑,只不过威力变小了,因为每次出招都要计算一次。而且修炼的时候也更加难了,因为每练一招就要在纸上记录下双剑之和,而且还需要用脑子算,速度比合一刀法慢了不少。

哇哈哈,剑侠仰天长笑!他给自己的剑法取名“优雅合一剑法”,意即他的剑法比合一刀法虽然威力不及,但也差不多少。最重要的是,他克服了合一刀法鲁莽不计后果的弱点,所以要比合一刀法来得优雅。但是这个剑法也有弱点,就是他额外增加了一张纸和用了更多的脑筋来计算。脑子计算倒是不成问题,努力学习算法便可,但是额外增加了一张纸,这个难免有些遗憾,但是也没有办法,总比独行侠那一套自保好得多。自保的代价是修炼一个平时几乎用不到的影子,是一比一。优雅合一剑法是二比一,降低了修炼的代价,而威力却较合一刀法没减多少。

然而,这套剑法虽然声名大噪,但是优雅剑侠还是被一个突如其来的问题一直折磨着,直到临终也没有想出办法解决。

疑问: 如果我使用3把剑、4把剑、5把剑,这套剑法还奏效么?因为3把剑的数字之和,就不是一个数字,而是两个数字了,比如1+0+1=10。而这套剑法只有一张纸,一个格不能放两个数字,这样就必须再加一张纸,这样不就和独行侠那一套无异了么?比例太高,不妥。所以优雅剑侠一直再考虑这个问题,临终前留下一段诗句,也抱憾而终。

独行合一皆非道,

二者中庸方优雅。

加减算术勤思考,

世间正道为算法!

优雅剑侠这段诗的最后一句,指明了后人若要解决这个问题,必须要找到一种算法。不管多少个数字,如果掩盖一个数字,可以将其他数字代入这个算法,就可以得到被掩盖的数字的值。这在当时简直就是不可能的事。“世间正道为算法”这句话后来被作为推动武林发展的一句至理名言。随着近代西方科技传入中国,这种算法终于被人了解了!他是如此简单而美丽!他改变了整个世界!

峰回路转,七星大侠在优雅剑法的基础上,把剑换成了磁盘。那张记录数字之和的纸,七星也改用磁盘来记录。这样,组成了一个三磁盘系统,两块数据盘,一块所谓“校验盘”。当数据损坏时,根据校验盘上的数字,可恢复损坏磁盘上的数字。两个磁盘系统每次只能传输2路数据,因为数据盘就两块,而每块磁盘每次就传输出去一路。

RAID 2的具体实现如图4-5所示。

图4-5 RAID 2的具体实现

看看RAID 2的具体实现。值得研究的是,七星大侠并没有使用加减法来进行校验,而是用了一种算法复杂的所谓“汉明码”来校验。这可不是信手拈来,而是有一定原因的。用加减算法进行校验,并没有对数据纠错的能力。加减法情况下,比如1+0+1=10,这段数据在从磁盘被传输给控制器的时候,校验位会一同传输,即数据位101,校验位10,此时经过控制器的校验,他会算出1+0+1=10,和一同传过来的校验位进行比对。如果相同,则证明数据都无误。但是此时如果在传输的过程中,电路受到干扰,数据位其中有一位畸变了,比如变成111了,也就是中间那个0变成1了,其他不变,此时控制器进行计算1+1+1=11,和一同传过来的10不同,那么控制器会怎么认为?它可以认为数据位全部正确,而校验位被畸变,也可以认为数据位被畸变,校验位正确。所以根本不能判断到底是哪种情况,所以不能修复错误。而七星引入了汉明码,汉明码的设计使得接收方可以判断到底是哪一位出错了,并且能修正一位错误,但是如果有两位都错了,那么就不能修正了。

Hamming Code ECC(汉明码错误检测与修正)

RAID 2算法的复杂性在于它使用了很早期的纠错技术——汉明码(Hamming Code)校验技术。现在就来看一下汉明码的算法。

汉明码在原有数据位中插入一定数量的校验位来进行错误检测和纠错。比如,对于一组4位数据编码为例,汉明码会在这4位中加入3个校验位,从而使得实际传输的数据位达到7位,它们的位置如图4-5所示。

需要被插入的汉明码的位数与数据位的数量之间的关系为2P≥P+D+1,其中P代表汉明码的个数,D代表数据位的个数。比如4位数据,加上1就是5,而能大于5的2的幂数就是3(23=8,22=4)。所以,7位数据时需要4位汉明码(24>4+7+1),64位数据时就要7位汉明码(27>64+7+1)。

在RAID 2中,每个IO下发的数据被以位为单位平均打散在所有数据盘上。如图4.5中所示,左边的为数据盘阵列,如果某时刻有一个4KB的IO下发给这个RAID 2系统,则这4KB中的第1、5、9、13等位将被存放在第一块数据盘的一个扇区中,第2、6、10、14等位被存放在第二个磁盘的对应条带上的扇区,依此类推。这样,数据强行打散在所有磁盘上,迫使每次IO都要全组联动来存取,所以此时要求各个磁盘主轴同步,才能达到最佳效果。因为如果某时刻只读出了一个IO的某些扇区,另一些扇区还没有读出,那么先读出来的数据都要等待,这就造成了瓶颈。主轴同步之后,每块磁盘盘片旋转同步,某一时刻每块磁盘都旋转到同一个扇区偏移的上方。同理,右边的阵列(我们称之为校验阵列)则存储相应的汉明码。

RAID 2在写入数据块的同时还要计算出它们的汉明码并写入校验阵列,读取时也要对数据即时地进行校验,最后再发向系统。通过上文的介绍,我们知道汉明码只能纠正一个位的错误,所以RAID 2也只能允许一个硬盘出问题,如果两个或以上的硬盘出问题,RAID 2的数据就将受到破坏。

RAID 2是早期为了能进行即时的数据校验而研制的一种技术(这在当时的RAID 0、1等级中是无法做到的),从它的设计上看也是主要为了即时校验以保证数据安全,针对了当时对数据即时安全性非常敏感的领域,如服务器、金融服务等。但由于校验盘数量太多、开销太大及成本昂贵,目前已基本不再使用,转而以更高级的即时检验RAID所代替,如RAID 3、5等。

七星大侠现在已经创造了三种阵式了,根据合一刀法所创的RAID 0,根据独孤掌所创的RAID 1,根据优雅合一剑法所创的RAID 2。而七星大侠的郁闷之处和当年优雅剑侠一样,就是苦于找不到一种一劳永逸的绝妙算法,一种集各种优点为一身而且开销小的算法。

4.1.4 RAID 3阵式

话说到了清末,清政府开展洋务运动,师夷长技以治夷。还别说,真引入了不少好技术,比如布尔逻辑运算式。这话要从布尔说起,布尔有一次在家捣鼓继电器,他将多个继电器时而串联,时而并联,时而串并一同使用,逐渐摸索出一些规律。比如两个继电器在串联时,必须同时闭合两个开关,电路才能接通,灯泡才能亮。如果把开关闭合当作1,开关关闭当作0,灯泡点亮当作1,灯泡不亮当作0,那么这种串联电路的逻辑就可以这样写:1和1=1。也就是两个开关都闭合,灯泡才能亮(等于1)。

然后,他还发现一个逻辑,如果在这个串联电路上增加一个元件,如果两个开关都闭合的时候,电路反而是断开的。有人说不可能,那么请仔细想一想,闭合开关电路断开,这有什么难的么?完全可以通过继电器来实现,比如电路闭合之后,电磁铁通电,把铁片吸引下来,而这个铁片是另一个电路的开关,铁片下来了,另一个电路也就断开了,所以通过把这两个电路组合,完全可以得到这种逻辑:1和1=0。

还有一种逻辑,就是当两个开关任意一个闭合时,电路就通路,也就是并联电路。这种逻辑可以这么表达:1或1=1,1或0=1。经过多种组合,布尔得到了1或1=1、1或0=1、1和1=1、1和0=0。

这就是4种基本逻辑电路。这种“和”、“或”的运算,很多人都不理解。人们理解的只是加减运算,因为加减很常用。人们不理解的原因就是不知道除了加减算术之外,还有一种叫做“逻辑”的东西,也就是因果的运算。人们往往把1当成数量,代表1个,而在因果率中,1不代表数量,它只代表真假,其实我们完全可以不用1这个符号来代表真,我们就用中文“真”代表真,可否?

当然可以,但是因为笔画太多,不方便,还是用1和0代表真假比较方便。其实磁盘上的数据,也不是1就代表1个,而是1代表磁性的取向,因为磁性只有两个取向,仿佛对称就是组成宇宙的基石一样,比如正、负,对、错等。当因果率被用数学方程式表达出来并赋予电路的物理意义之后,整个世界也就进入了新世纪的黎明,这个世纪是计算机的世纪。

提示: 从数学到物理意义,我们仿佛看出点什么来,现代量子力学那一大堆数学式,折服了太多的科学家,包括爱因斯坦,到他去世前,爱因斯坦都没有理解量子力学所推演出来的数学式子在物理上到底代表了什么意义。而且直到21世纪,也没有人给予这些式子以“目前”可理解的物理意义。我们可以想象一下布尔逻辑算式公布的时候,物理意义到底是什么?没人知道,甚至布尔自己估计也不知道,就只是一对式子而已。直到有一天一个人在家捣鼓继电器,突然风马牛不相及地想到了,这不就是布尔逻辑么?从此,数字电路,计算机时代,改变了我们的世界。

七星在学习了布尔逻辑算式之后,也是稀里糊涂地把它用在RAID 2那一直困扰他的问题上面,看看能否有所突破。

布尔运算中有一个XOR运算,即1 XOR 0=1,1 XOR 1=0,0 XOR 0=0。布尔也总结出了与加法结合率、加法交换率等类似的逻辑运算率,并发现了一些规律:

1 XOR 0 XOR 1=0
0 XOR 1 XOR 0=1

假如第一个式子中,中间的0被掩盖,完全可以从结果推出这个被掩盖的逻辑数字。不管多少位,进行逻辑运算之后还是一位。仔细一想也是理所当然的,逻辑结果只有两个值,不是真,就是假,当然只用一位就可以代替了。

提示: 大家可以自己算算,不管等式左边有多少位进行运算,这个规律都适用。但是在加减法中,若要保持等式右边有一位,则左边参与运算的只能是1+0或者0+1,再多一个数的话,右边就是两位了。但是逻辑运算中等式右边永远都是一位!就是如此绝妙。为什么如此精妙呢?没人能解释为什么,就像问为什么有正电荷、负电荷一样,它们到底是什么东西,谁也说不清。

七星大侠开始并不觉得这是真的,他反复演算,想举出一个伪证,可是徒劳无功。七星不得不为布尔的绝学所折服!同时也为西方发达的基础科学所赞叹!

至此,困扰七星大侠多年的关于算法的问题,终于随着西方科学的介入,得以顺利解决!而且解决得是那么完美,那么畅快!

七星立即决定投入其下一个阵式RAID 3的创立过程中。他发狂似地抛弃了那冗余的让人看着就不顺眼的RAID 2的几块校验盘,只留下一块。按照布尔的思想,数据盘的每一个位之间做XOR运算,然后将结果写入校验盘的对应位置。这样,任何一块数据盘损坏,或者其中的任何一个扇区损坏,都可以通过剩余的位和校验位一同进行XOR运算,而运算的结果就是这个丢失的位。8位一起校验可以找出一个丢失的字节,512字节一起校验就可以找到一个丢失的扇区。

做到这里,已经算是成功了,但是七星还不太满足,因为他还有一桩心事,就是RAID 2中数据被打得太散了。七星大侠索性把RAID 3的条带长度设置成为4KB,这样刚好适配了上层的数据组织,一般文件系统常用的是以4KB为一个块。如果用4块数据盘,则条带深度为两个扇区或者1KB。如果用8个数据盘,则条带深度为1个扇区或者说512B。总之,要保持条带长度为上层块的大小。上层的IO一般都会以块为单位,这样就可以保证在连续写的情况下,可以以条带为单位写入,大大提高磁盘并行度。

七星在RAID 3阵式中,仍旧保持RAID 2的思想,也就是对一个IO尽量做到能够分割成小块,让每个磁盘都得到存放这些小块的机会。这样多磁盘同时工作,性能高。所以七星在RAID 3中把一个条带做成4KB这个魔术值,这样每次IO就会牵动所有磁盘并行读写。到此我们了解了,RAID 2和RAID 3都是每次只能做一次IO(在IO块大于Block SIZE的时候),不适合于要求多IO并发的情况,因为会造成IO等待。RAID 3的并发只是一次IO的多磁盘并发存取,而不是指多个IO的并发。所以和RAID 2一样,适合IO块大、IO SIZE/IO PS比值大的情况。

提示: 在极端优化的条件下,RAID 3也是可以做到IO并发的。控制器向一块磁盘发送的读写指令,其中包含一个所要读取扇区的长度,如果下一次IO与本次IO在物理上是连续的(连续IO),此时如果控制器做了极端的优化,则可以将这两次IO合并起来,向磁盘发送的每个IO指令中包含了两次上层IO的数据,这样也算是一种并发IO。当然,这种优化不仅仅可以在磁盘控制器这一层实现,其实文件系统层也可以实现。

提示: RAID 3和RAID 2一样,要达到RAID 3的最佳性能,需要所有磁盘的主轴同步。也就是说,对于一块数据,所有磁盘最好同时旋转到这个数据所在的位置,然后所有磁盘同步读出来。不然,一旦有磁盘和其他磁盘不同步,就会造成等待,所以只有主轴同步才能发挥最大性能。

总结一下,RAID 3相比RAID 2校验效率提升,成本减少(使用磁盘更少了)。缺点是不支持错误纠正了,因为XOR算法无法纠正错误。但是这个缺点已经不重要,发生错误的机会少之又少,可以完全靠上层来处理错误了。正可谓:

与非异或同,

一语解千愁。

今朝有酒醉,

看我数风流!

下面说明关于RAID 3的校验盘有没有瓶颈的问题。

不妨用一个例子来深入理解一下RAID 3。通过刚才的讲解,大家知道了RAID 3每次IO都会分散到所有盘。因为RAID 3把一个逻辑块又分割成了N份,也就是说如果一个逻辑块是4KB(一般文件系统都使用这个值),在有5块盘的RAID 3系统中其中4块是数据盘,1块是校验盘。这样,把4KB分成4块,每块1KB,每个数据盘上各占1块,也就是两个扇区。而文件系统下发的一个IO,至少是以一个逻辑块为单位的,也就是不能IO半个逻辑块的单位,也就不可能存在一个IO,大小是小于4KB的,要么是1个4KB,要么是N个4KB。但这只是针对文件系统下发的IO,磁盘控制器驱动向磁盘下发的IO最细粒度可以为一个扇区。这样,就保证了文件系统下发的一次IO,不管多大都被跨越了所有数据盘。

读又分成连续读和随机读。连续读指的是每个IO所需要提取的数据块在序号上是连续的,磁头不必耗费太多时间来回寻道,所以这种情况下寻道消耗的时间就很短。我们知道,一个IO所用的时间约等于寻道时间加上旋转延迟时间再加上数据传输时间。IOPS=1/(寻道时间+旋转延迟时间+数据传输时间),由于寻道时间相对于传输时间要大几个数量级,所以影响IOPS的关键因素就是寻道时间。而在连续IO的情况下,仅在换磁道时需要寻道,而磁道都是相邻的,所以寻道时间也足够短。在这个前提下,传输时间这个分母就显示出作用来了。由于RAID 3是一个IO,必定平均分摊到了N个数据盘上,所以数据传输时间是单盘的1/N,从而在连续IO的情况下,大大增加了IOPS。而磁盘总体传输速率约等于IOPS乘以IO SIZE。不管IO SIZE多大,RAID 3的持续读性能几乎就是单盘的N倍,非常强大。

再看看持续写,同样的道理,写IO也必定分摊到所有数据盘,那么寻道时间也足够短(因为是持续IO)。所以写的时候所耗费的时间也是单盘的1/N,因此速率也是单盘的N倍。有人说RAID 3的校验盘是热点盘,是瓶颈。理由是RAID 3写校验的时候,需要像RAID 5一样,先读出原来的校验块,再读出原来的数据块,接着计算出新校验,然后写入新数据和新校验。实际上RAID 3中每个IO必定要改动所有数据盘的数据分块。因为一个文件系统IO的块已经被分割到所有盘了,只要这个IO是写的动作,那么物理磁盘上的所有分块,就必定要全部都被更新重写。既然这样,还有“旧数据”和“旧校验”的概念么?没有了,因为这个IO上的所有分割块需要全部被更新,包括校验块。数据在一次写入之前,控制器就会计算好校验块,然后同时将数据块和校验块写入磁盘。这就没有了什么瓶颈和热点的区别!

RAID 4是有热点盘,因为RAID 4系统处理文件系统IO不是每次都会更新所有盘的,所以它必须用RAID 5的那个计算新校验的公式,也就是多出4个操作那个步骤,所以当然有瓶颈了!要说RAID 3有热点盘,也行,所有盘都是热点盘,数据、校验,所有盘,对RAID 3来说,每次IO必将牵动所有盘,那么就可以说RAID 3全部都是热点盘!

再来看看RAID 3的随机读写。所谓随机IO,即每次IO的数据块是分布在磁盘的各个位置,这些位置是不连续的,或者连续几率很小。这样,磁头就必须不断地换道,换道操作是磁盘操作中最慢的环节。根据公式IOPS=1/(换道时间+数据传输时间),随机IO的时候换道时间很大,大出传输时间几个数量级,所以传输得再快,翻10倍也才增高了一个数量级,远不及换道时间的影响大,所以此时可以忽略传输时间的增加效应。由于一次IO同样是被分割到了所有数据盘,那么多块盘同时换道,然后同时传输各自的那个分块,换道时间就约等于单盘。其传输时间是单盘的1/N,而传输时间带来的增效可以忽略。所以对于随机读写的性能,RAID 3并没有提升,和单盘一样,甚至不及单盘。因为有时候磁盘不是严格主轴同步的,这样换道慢的磁盘会拖累其他磁盘。

再来看看并发IO。显然,RAID 3执行一次IO必将牵动占用所有盘,那么此时其他排队的IO就必须等待,所以RAID 3根本就不能并发IO。

注意: 上文中的“IO”均指文件系统下发的IO,而不是指最终的磁盘IO。

4.1.5 RAID 4阵式

七星自从学习了西方先进的基础科学之后,一发而不可收。以前已经是以钻研为乐,现在成了以钻研为生了。以前饿了还知道去要饭吃,现在七星已经感觉不到饿了,只要有东西让他钻研,就等于吃饭了。

话说某天七星正在闭目思考修炼,他回想起了双刀时代的辉煌、独行时代的凄苦和优雅剑时代的中庸之乐。往事历历在目,再看看如今已经是穷困潦倒的自己,他不禁潸然泪下,老泪纵横。

他给上面的三种思想,分别划分了门派,RAID 0属于激进派,RAID 1属于保守派,RAID 2,RAID 3属于中庸派。中庸派的思想一方面汲取了激进派的横分竖割提高威力的做法,一方面适当地降低威力来向保守派汲取了自保的经验,而创立了引以为豪的校验盘的绝妙技术。

七星想着激进派似乎已经没有什么可以让中庸派值得借鉴的地方了,倒是保守派的一个关键技术中庸派还没有移植过来,那就是同时应付多个敌人的技术。虽然当年独行侠根本就没有意识到他的独孤影子掌可以同时应付两个敌人,因为独行侠一生都没有同时和两个人交过手。虽然独孤掌的秘笈中也没有提及这门绝招,但是七星凭他积累多年的知识和经验,强烈地感觉到并发IO早在独孤掌时代就已经被实现了,只不过没有被记载,而且一直被人忽略!要想有所突破就必须突破这一关!想到这里,七星立即再次开始了他的实验。

RAID 2阵式中,数据块被以位为单位打散在多块磁盘上存储,这种设计确实应该被淘汰了,且不说IO设计合理与否,看它校验盘的数量就让人气不打一处来。那么再看看RAID 3,在RAID 3的IO设计中还是走了RAID 2的老路子,也就是一次IO尽量让每块磁盘都参与,而控制器的一次IO数据块不会很大,那么想让每块磁盘都参与这个IO,就只能人为地减小条带深度的大小。

事实证明这种IO设计在IOSIZE/IOPS(比值)很大的时候,确实效果明显。但在现实应用中,很多应用的IOSIZE/IOPS都很小,比如随机小块读写等,这种应用每秒产生的IO数目很大,但是每个IO所请求的数据长度却很短。如果所有磁盘同一时刻都被一个IO占用着,且不能并发IO,只能一个IO一个IO的来做,由于IO块长度小,此时全盘联动来传输这个IO,得不偿失,还不如让这个IO的数据直接写入一块磁盘,空余的磁盘就可以做其他IO了。

要实现并发IO,就需要保证有空闲的磁盘未被IO占用,以便其他IO去占有磁盘进行访问。唯一可以实现这个目的的方法就是增大条带深度,控制器的一个IO过来,如果这个IO块小于条带深度,那么这次IO就被完全“禁锢”在一块磁盘上,直接就写入了一个磁盘上的Segment中,这个过程只用到了一块磁盘。而其他IO也可以和这个IO同时进行,前提是其他IO的目标不是这个IO要写入或读取的磁盘。所以实现IO并发还需要增大数据的随机分布性,而不要连续在一个磁盘上分布。这里七星大侠忽略了一个非常重要的地方,下面会看到。

在这些分析的基础上,七星将RAID 3进行了简单的改造,增大了条带深度,于是便创立了一个新的阵式,名曰RAID 4。

四海一家

先      并

来      肩

后      携

到      手

先      并

进      存

先      并

出      取

天      海

经      誓

地      山

义      盟

4.1.6 RAID 5阵式

话说七星大侠正在为创立了RAID 4阵式而欢喜的时候,麻烦来了。很多江湖上的朋友都给他捎信说,修炼了RAID 4阵式之后,在IO写的时候,好像性能相对于RAID 3并没有什么提升,不管IOSIZE/IOPS的值是多少。这个奇怪的问题,让七星大侠天天如坐针毡、茶饭不思,终日思考这个问题的原因。他不停地拿着两块磁盘和一张纸(校验盘)比划。时间一长,七星有一天突然发现,纸已经被他画的不成样子了,需要另换一张。这引起了思维活跃的七星大侠的思考,“并发IO,并发IO,并发IO,……”,他不停地在嘴里念叨着。突然他两眼一睁,骂了一句之后,开始奋笔疾书。

七星大侠想到了什么让他恍然大悟呢?原来,七星经过思考之后,发现RAID 4确实是他的一大败笔,相对RAID 3没有什么性能提升,反而误人子弟,浪费了很多人的时间去修炼一个无用的功夫。

七星创立RAID 4时,太过大意了,竟然忽略了一件事情。每个IO写操作必须占用校验盘,校验盘每一时刻总是被一个IO占用,因为写数据盘的时候,同时也要读写校验盘上的校验码。所以每个写IO不管占用了哪块数据盘,校验盘它是必须占用的,这样校验盘就成为了瓶颈,而且每个写入IO都会拖累校验盘,使得校验盘没有休息的时间,成了“热点盘”,非常容易损坏。

没有引入校验功能,数据盘可以被写IO并发,引入了校验功能之后,数据盘还可以并发,但是校验盘不可以并发,所以整体上还是不能并发。除非不使用校验盘,不过那就和RAID 0没什么区别了。所以七星在RAID 4上掉进了一个误区,如今他终于醒悟了。

创立的RAID 4什么都不是,不伦不类。七星这个郁闷啊!为了实现真正的写IO并发,他这次是豁出去了,一定要创立新的阵式!

思考: RAID 4的关键错误在于忽略了校验盘。每个IO不管目标在哪个数据盘,但是一定要读写校验盘。而校验盘只有一块,不读也得读!那如果有两块校验盘,它能否随机选择一块来读写?不行,这两块校验盘之间也要同步起来,类似RAID 1,这样开销太大,成本太高。

不妨作一下演绎,首先,我们的目标是并发IO。要并发IO,校验盘某一时刻必须可以被多个IO占用,这是必须的,否则就不是并发IO。但是“校验盘某一时刻可以被多个IO占用”,这不简直是扯淡么?一块磁盘怎么可以同时被多个IO占用呢?所以七星下了结论,中庸派不可能实现并发IO。

结论下了,七星也病了,彻彻底底的病倒了。他不甘心,在他心中一定有一个完美的阵式。他拿着那张已经快被画烂的纸,气愤至极,将纸撕成了两半。碎片就像七星那破碎的心,飘飘落下,不偏不倚,正好分别落到了地上的两把剑上,分别盖住了剑的一半。七星看着这情景,一发愣,仿佛冥冥中一直有个神仙在指引着他似的,又一次让七星茅塞顿开,恍然大悟:“老天助我啊!哇哈哈哈哈哈!”

七星疯了一般从炕上滚落下来,他又找来一把剑,把纸撕成三块,分别盖住每把剑的三分之一。同样,4把剑,把纸撕成4块,盖住剑的四分之一。良久之后,七星仰天长叹:“完美,太完美了!”

七星赶紧静下心来,他深知,必须经过深思熟虑,才不会出现问题,不能重蹈RAID 4的覆辙。他花了半个月的时间,用树枝在地上画图演算,并仔细分析。一块磁盘同一时刻不能被多个IO占用,这是绝对真理,不可质疑的真理。那么以前也曾经想过,把校验盘做成多块,可否?也不好,不完美。这次把校验盘分割开,组合于数据盘之中,依附于数据盘,这样就完美地避开了那个真理。既然多个IO可以同时刻访问多块数据盘,而校验盘又被打散在各个数据盘上,那么就意味着多IO可以同时访问校验盘(的“残体”)。这样就大大增加了多IO并发的几率,纵使发生多个IO所要用到的校验盘的“残体”可能在同一块数据盘上,这样还是可以IO排队等待的。

如果数据盘足够多,校验盘打散的部分就会分布得足够广泛,多IO并发的几率就会显著增大!他根据这个推断做实验,首先是两个数据盘。把纸撕成两半,分别盖住两把剑的一半,这样实际的数据盘容量其实是一把剑的容量,校验盘容量也是一把剑的容量,它们分别占了总容量的二分之一。由于2块盘的RAID 5系统,对于写操作来说不能并发IO,因为一个IO访问其中一块盘的数据的时候,校验信息必定在另一块盘,必定也要同时访问另一块盘。同样,3块盘的RAID 5系统也不能并发IO,最低可以并发IO的RAID 5系统需要4块盘,而此时最多可以并发两个IO,可以算出并发几率为0.0322。更多磁盘数量的RAID 5系统的并发几率将更高。图4-6为一个RAID 5系统的示意图。

图4-6 RAID 5系统示意图

七星这次可谓是红星高照,脸色红润,病态全无。他把这个新创立的阵式叫做RAID 5。正可谓:

心似剑,剑如心,

剑心合,方不侵。

分久必合合久分,

分分合合天地真!

RAID 5也不是那么完美无缺的,可以说RAID 5是继RAID 0和RAID 1之后,又一个能实现并发IO的阵式,但是比RAID 1更加划算,比RAID 0更加安全。RAID 5浪费的资源,在2块盘的系统中与RAID 1是一样的,都是二分之一。但是随着磁盘数量的增加,RAID 5浪费的容量比例越来越小,为N分之一,而RAID 1则永远是二分之一。

RAID 5和RAID 0都是利用条带来提升性能,但是它又克服了RAID 0的鲁莽急躁,对数据用校验的方式进行保护。但是RAID 5的设计思想,注定了它的连续读性能不如RAID 3,RAID 3由于条带深度很小,每次IO总是能牵动所有磁盘为它服务,对于大块连续数据的读写速度很快。但是RAID 5的条带深度比较大,每次IO一般只使用一块数据盘,而且通用RAID 5系统一般被设计为数据块都是先放满一个Segment,再去下一个磁盘的Segment存放,块编号是横向进行的。

RAID 5在随机读方面,确实是首屈一指的,这要归功于它的多IO并发的实现,这里指的是随机IO。也就是说RAID 3在IOSIZE值大的时候具有高性能,RAID 5在随机IOPS大的时候具有高性能。

RAID 5的一大缺点就是写性能较差。写性能差是中庸派的通病,其根本原因在于它们每写一扇区的数据就要产生其校验扇区,一并写入校验盘。尤其是更改数据的时候,这种效应的影响尤其严重。

RAID 5写的基本过程是这样的,新数据过来之后,控制器立即读取待更新扇区的原数据,同时也要读取这个条带上的校验数据。三者按照公式运算,便可得出新数据的校验数据,然后将新数据和新数据的校验数据写到磁盘。公式如下:

新数据的校验数据=(老数据 EOR 新数据)EOR 老校验数据

鱼和熊掌不可兼得!最后七星总结了这么一句话。也就是说随机并发IO和写性能二者取其一。但是有些文件系统巧妙地减少了这种写惩罚,使得RAID 4的缺点被成功削减,从而将其优点显现了出来,本章后面会提到这种优化操作。

思考: RAID 5一次写的动作,其实要浪费掉3个其他动作,也就是要先读出老数据,读出老校验数据,然后写新数据和校验数据,这样只有“写新数据”是要完成的目的,而捎带了三个额外操作。纵观RAID 0和RAID 1此二者,RAID 0鲁莽,写就是写,不带任何考虑,所以速度最快。RAID 1自保,但是每次也只要写两次即可,只是额外多了一个操作。所以RAID 5和RAID 4在处理写方面是失败的。就连RAID 2和RAID 3都比RAID 5写性能强,因为它们的条带深度很小,任何一次正常点的IO几乎会覆写所有盘,均会将这整个条带上的位都改变。所以RAID 2和RAID 3不用顾忌条带上是否还有未被更新的数据,所以它不会管老数据如何,只管从新数据计算出新校验数据,然后同时将数据位和校验位分别写到数据盘和校验盘,这样只用了两个操作,比RAID 5少了两次读的过程。

RAID 5E和RAID 5EE阵式

七星大侠推出RAID 5之后,得到了极为广泛的应用,江湖上的武林人士都在修炼,有些练成的大侠还各自创办了数据库、网站等生意,得益于RAID 5的随机IO并发特性,这些人赚了一大笔,生意火得一塌糊涂。然而,七星还是那个要饭的七星,剑还是那把剑,依然终日以钻研为乐,以钻研为生。

话说有一天,有个侠客专门找到了七星大侠,侠客请他到“纵横斋”煮酒畅饮。酒过三巡,菜过五味,侠客进入了正题,向七星叙述了一件事情。他说他已经炼成了RAID 5阵式,但是在使用的时候总是心里没底。其原因就是一旦一块磁盘损坏,虽然此时不影响使用,但是总有顾虑,不敢全力出招,就怕此时再坏一块磁盘,整个阵式就崩溃了。

他请求七星解决这个问题,临走的时候留下了几块市面上品质最好的硬盘和一些银子供七星研究使用。七星很是感动,几十年来从来没有一位江湖人士和他交流切磋过,也从来没有一个人来帮助过他。此景让他泪流满面,感动得不知说什么好。他向那位侠客道:“能交您这位豪杰人士,我七星此生无憾!”随后,七星又开始终日研究。这位大侠就是几十年后谱写降龙传说的张真人。

思考: 嗯,一旦一块磁盘损坏,此时这块盘上的数据已经不复存在,但是如果有IO请求这块坏盘上的数据,那么可以用还存在的数据,校验出这块损坏的数据,传送出去。也就是说,损坏的数据是边校验边传送,现生成现传送的。而对于要写入这块盘的IO,控制器会经过计算,将其“重定向”到其他盘。所谓重定向并不是完全透明地写入其他盘,而是运用XOR进行逆运算,将写入的数据代入算式进行逆运算,得到的结果写入现存的磁盘上。

此时如果再有一块磁盘损坏,无疑阵式就要崩溃了。解决这个问题的直接办法,就是找一块备用的磁盘。一旦有磁盘损坏,其他磁盘立即校验出损坏的数据,立即写到备用磁盘上。写完之后,阵形就恢复原样了,就没有顾虑了。但是必须保证在其他磁盘齐力校验恢复数据的过程中,不可再有第二块磁盘损坏,不然便会玉石俱焚!

想到这里,七星开始了他的实验,并且取得成功。就是在整个阵式中增加一块热备盘,平时这块磁盘并不参与组阵,只是在旁边观战,什么也不干。一旦阵中某个人受伤不能参战了,这个热备盘立即顶替他,其他人再把功力传授给他。传授完毕后,就像原来的阵式一样了。如果在大家传授功力的时候,有IO请求这块损坏磁盘上的数据,那么大家就暂停传授,先应付外来的敌人。当没有来针对这块损坏磁盘的挑衅时,大家会继续传授。

七星的经验不断丰富,他知道不能急躁,所以实验成功之后,七星并没有马上通知那位大侠,而是继续在想有没有可以改进的地方。他想,热备盘平时不参与组阵,那就不能称作阵式的一部分,而是被排斥在外。这块磁盘平时也没有IO,起不到作用,这样就等于浪费了一块磁盘。那么是不是考虑也让它参与到阵形中来呢?如果要参与进来,那让它担任什么角色呢?热备角色?如果没有人受伤,这个角色在阵中只会是个累赘。怎么办好呢?七星忽然掠过一丝想法,是否可以让阵中各个角色担待一下,从各自的领地保留出一块空间,用作热备盘的角色呢?

这样把热备盘分布在各个磁盘上,就不会形成累追,并且同时解决了热备盘和大家不协调的问题。说干就干,七星给那位大侠写了一封信,信中称这种阵式为RAID 5E。七星继续琢磨RAID 5E,让阵中每个人都保留一块领地,而不横割,虽然可以做到数据的及时备份,但是这块领地总显得不伦不类。七星突然想到被撕碎的纸片飘然落下的情景,忽然计上心头!既然校验盘都可以横分竖割的融合到数据盘,为什么热备盘不能呢?一样可以!七星想到这里,于是又给那位侠客去了一封信,信中描述这种新的阵式为RAID 5EE。

那位侠客给七星回了一封信:

七星转,北斗移,

英雄无谓千万里。

待到再次相见时,

白发苍,叙知己!

七星看后老泪纵横,颇为感动。相见恨晚啊,到了晚年才遇到人生知己!

4.1.7 RAID 6阵式

如今,七星已经从一个壮小伙变成了个孤苦伶仃的老头。回首过去,从RAID 0一直到RAID 5(E、EE)创立了6种阵式,各种阵式各有所长。他最得意的恐怕就是中庸派的中庸之道。可就是这个中庸之道,却还有一个一直也未能解决的问题,那就是其中任何一种阵式,都最多同时允许损坏一块磁盘,如果同时损坏多块,整个阵不攻自破!七星想到这里就一阵酸楚。已经是白发苍苍的七星老侠,决定要用晚年最后一点精力来攻破这个难题。

七星老侠一生精研阵式,有很多宝贵的经验。他这次采用了逆向思维,假设这个模型已经做好,然后从逆向分析它是怎么作用的。先描绘出多种模型,然后一个一个地去攻破,找出最适合的模型。

七星描绘了这么一个模型,假设有5块盘组成一个RAID阵列,4块数据盘,一块校验盘,那么同一时刻突然4块数据盘中的两块损坏作废,只剩下两块数据盘和一块校验盘。假设有某种算法,可以恢复这两块丢失磁盘上的数据,那么怎么从这个模型推断出,这个算法是怎么把丢失的两块盘数据都恢复出来的呢?七星冥思苦想。七星在幼年学习方程的时候,知道要求解一个未知数,只需知道只包含这一个未知数的一个等式即可逆向求解。就像布尔的逻辑算式用在RAID 3阵式时候一样,各个数据盘上的数据互相XOR之后就等于校验盘上的校验数据,这就是一个等式:

D1 XOR D2 XOR D3 = Parity

如果此时D1未知,而其他3个值都已知,那么就可以逆向解出未知数,而这也是RAID 3进行校验恢复的时候所做的。那么此时如果D1和D2都未知,也就是1号盘和2号盘都损坏了,还能解出这两个值么?数学告诉七星,这是不可能的,除非除了这个等式还额外存在一个和这个等式不相关的另一个等式!

要求解两个未知数,只要知道关于这两个未知数的不相关的两个关系方程即可。比如有等式为D1?D2?D3 = *,联立以上两个等式,即可求出D1和D2。七星开始寻觅这个等式,这个等式是已经存在?还是需要自己去发明呢?七星一开始打算从布尔等式找寻出第二个等式的蛛丝马迹,但是后来他根据因果率知道如果从布尔等式推出其他某些等式,那么推出的等式和布尔等式就是相关的。互相相关的两个等式,在数学上是等价的,无法作为第二个等式。七星有所察觉了,他认为要想得出第二个等式,必须由自己发明一套算法,一套和布尔等式不相关的算法!他开始在纸上演义算法,首先他开始从算术的加减方程开始着手,他写出了一个可以求解两个未知数的二元方程:

x+y=10
2x+3y=20

这算是最简单的算术方程了。可以求得x=10,y=0。

以上是对于算术运算的方程,那么布尔逻辑运算是否也可以有方程呢?七星写下如下的式子:

x XOR y = 1
Ax XOR Bx = 0

第一个方程已经存在了,也就是用在RAID 3上的校验方程。第二个方程是七星模仿加减方程来写的,也就是给x和y两个值分别加上了一个系数,而这两个系数不能是从第一个等式推得的,比如是将第一个等式未知数的系数同乘或同除以某个数得出来的,这样就是相关等式了。七星立即找来布尔逻辑运算方面的书深入学习,终于得到了印证,这种方程确实存在!七星激动得跳了起来!他立即投入到研发中。过了两个月,终于得出了结果!大获成功!

七星对一份数据使用两套算法各自算出一个等式,1号等式右边的结果写入校验盘1、2号等式右边的值写入校验盘2。这样,只要使用中有两个值发生丢失,就可以通过这两个等式联立,解出丢失的两个值。不管这两个值是等式左边的还是等式右边的,只要代入这两个等式中,就可以求出解。

数学的力量是伟大的,任何东西只要通过了数学的验证,就是永恒的!

同样,七星将用在RAID 5中的方法,用在了新创立的阵式中,将校验盘分布到数据盘中,不同的是新阵式的校验盘有两块,在每块磁盘上放置两个等式需要的校验值。

七星给这种阵式取名为RAID 6。

RAID 6相对其他各种中庸派的阵式安全多了,但同时它的写性能更差了,因为它要多读出一个校验数据,而且计算后还要写入一次,这就比RAID 5每次写耗费多了两个操作,变成了6次操作,所谓的“写惩罚”更大了。确实是鱼与熊掌不能兼得啊!正可谓:

寻寻觅觅终冷清,

七星北斗伴我行。

世间万物皆规律,

求得心法谋太平!

七星在创立了RAID 6阵式之后,已经老态龙钟,疾病缠身,所剩时日不多。而江湖上可是一派热闹,修炼的修炼,修炼好的就立门派,开设数据库、网站等服务来大赚钱财。而打着七星大侠旗号到处招摇撞骗的人也不在少数。张真人路见不平拔刀相助,他召开武林大会,表彰了七星的功绩,指出真正的七星现在早已归隐,那些招摇撞骗的人也就没有容身之地了。他还提议将七星所创立的7种阵式命名为“七星北斗阵”,以纪念他和七星之间的北斗豪情!

张真人亲自到深山去探望已经下不了床的七星,并将武林中发生的事情告诉了他。此后没几天,七星无憾地离开了人世,化作了北斗七星,在天上洒下无限的光芒照耀世间!张真人给老人办了后事,并将七星过世的消息宣布了出去。没想到第二天,七星、星七、北斗、斗北、七星北斗、北斗七星、星七北斗、星七斗北等商标就被抢注了!大批的商人在发着横财。正可谓:

七星赞

七星阵里论七星,

北斗光前参北斗。

不知天上七星侠,

如今过活要饭否?

4.2 七种RAID技术详解

下面从纯技术角度,深入剖析目前存在的七种RAID模式的组成原理和结构,并分析各种级别相对于单盘IO速率的变化。

首先澄清一点,所谓Stripe完全是由程序在内存中虚拟出来的,说白了就是一个map公式。即仿佛是给程序戴了一个特殊的眼镜,程序戴上这个眼镜,就能看到“条”和“带”,就会知道将数据分布到条带上了。一旦摘下这个眼镜,那么看到的就是普通的物理磁盘扇区。这个眼镜就是实现RAID的程序代码。物理磁盘上根本不存在什么“条”和“带”,只有扇区。另外,程序会在磁盘特定的一些扇区中写入自己运行时需要的信息,比如一些RAID标签信息等。

图4-7为一个RAID 0系统的示意图。

图4-7 一个典型的RAID 0系统

1.扇区、块、段(Segment)、条带、条带长度和深度

图4-7中的5个竖条,分别代表5个磁盘。然后在磁盘相同偏移处横向逻辑分割,形成Stripee。一个Stripee横跨过的扇区或块的个数或字节容量,就是条带长度,即Stripee Length。而一个Stripee所占用的单块磁盘上的区域,称为一个Segment。一个Segment中所包含的data Block或者扇区的个数或者字节容量,称为Stripee Depth。Data Block可以是N倍个扇区大小的容量,应该可调,或者不可调,由控制器而定。

RAID 0便是将一系列连续编号的Data Block分布到多个物理磁盘上,扩散IO提高性能。其分布的方式如图4-7所示。这个例子中,条带深度为4,则0、1、2、3号Data Block被放置到第一个条带的第一个Segment中,然后4、5、6、7号Block放置到第一个条带的第二个Segment中,依此类推,条带1放满后,继续放条带2。这种特性称为“局部连续”,因为Block只有在一个Segment中是物理连续的,逻辑连续就需要跨物理磁盘了。

2.关于几个与IO相关的重要概念

IO可以分为读/写IO、大/小块IO、连续/随机IO、顺序/并发IO、稳定/突发IO、持续/间断IO和实/虚IO。下面来分别介绍这几种IO。

(1)读/写IO

这个就不用多说了,读IO就是发指令从磁盘读取某段序号连续的扇区的内容。指令一般是通知磁盘开始扇区位置,然后给出需要从这个初始扇区往后读取的连续扇区个数,同时给出动作是读还是写。磁盘收到这条指令就会按照指令的要求读或者写数据。控制器发出这种指令加数据并得到对方回执的过程就是一次IO读或IO写。

注意: 一个IO所要提取的扇区段一定是连续的,如果想提取或写入两段不连续的扇区段,只能将它们放入两个IO中分别执行,这也就是为何随机IO对设备的IOPS指标要求较高的原因。

(2)大/小块IO

指控制器的指令中给出的连续读取扇区数目的多少。如果数目很大,如128、64等,就应该算是大块IO;如果很小,比如1、4、8等,就应该算是小块IO。大块和小块之间没有明确的界限。

(3)连续/随机IO

连续和随机是指本次IO给出的初始扇区地址和上一次IO的结束扇区地址是不是完全连续的或者相隔不多的。如果是,则本次IO应该算是一个连续IO;如果相差太大,则算一次随机IO。连续IO因为本次初始扇区和上次结束扇区相隔很近,则磁头几乎不用换道或换道时间极短。如果相差太大,则磁头需要很长的换道时间。如果随机IO很多,会导致磁头不停换道,效率大大降低。

(4)顺序/并发IO

意思是,磁盘控制器如果可以同时对一个RAID系统中的多块磁盘同时发送IO指令(当然这里的同时是宏观的概念,如果所有磁盘都在一个总线或者环路上,则这里的同时就是指向一块磁盘发送一条指令后不必等待它回应,接着向另一块磁盘发送IO指令),并且这些最底层的IO数据包含了文件系统级下发的多个IO的数据,则为并发IO。如果这些直接发向磁盘的IO只包含了文件系统下发的一个IO的数据,则此时为顺序IO,即控制器缓存中的文件系统下发的IO队列,只能一个一个来。并发IO模式在特定的条件下可以很大程度地提高效率和速度。

(5)持续/间断IO

持续不断地发送或者接受IO请求数据流,这种情况为持续IO;IO数据流时断时续则为间断IO。

(6)稳定/突发IO

某存储设备或者某程序在一段时间内接收或者发送的IOPS以及Throughput(吞吐量)保持相对稳定和恒定,则称为稳定IO;如果单位时间的IOPS或者Throughput突然猛增,则为突发IO。

(7)实/虚IO

某IO请求中包含对应实际数据地址的,比如磁盘LBA地址,或者文件偏移量,请求读或者写实际文件或者磁盘扇区数据的,称为实IO;而应用程序针对文件元数据操作的(在文件系统层以上没有文件主体数据操作),或者针对磁盘发送的非实体数据IO请求,比如Report LUN、SCSI Sense Request等控制性IO,称为虚IO。

(8)IO并发几率

单盘,IO并发几率为0,因为一块磁盘同时只可以进行一次IO。对于RAID 0,在2块盘情况下,条带深度比较大的时候(条带太小不能并发IO),并发两个IO的几率为1/2。其他情况请自行运算。

(9)IOPS

完成一次IO所用的时间=寻道时间+旋转延迟时间+数据传输时间,IOPS=IO并发系数/(寻道时间+旋转延迟时间+数据传输时间)。由于寻道时间相对于传输时间要大几个数量级,所以影响IOPS的关键因素就是降低寻道时间。在连续IO的情况下,寻道时间很短,仅在换磁道时候需要寻道。在这个前提下,传输时间越少,IOPS就越高。

(10)每秒IO吞吐量

显然,每秒IO吞吐量=IOPS×平均IO SIZE。IO SIZE越大,IOPS越高,每秒IO吞吐量就越高。设磁头每秒读写数据速度为V,V为定值。则IOPS=IO并发系数/(寻道时间+旋转延迟时间+IO SIZE/V)。代入得每秒IO吞吐量=IO并发系数×IO SIZE×V/(V×寻道时间+V×旋转延迟时间+IO SIZE)。可以看出影响每秒IO吞吐量的最大因素就是IO SIZE和寻道时间以及旋转延迟时间。IO SIZE越大,寻道时间越小,吞吐量越高。相比能显著影响IOPS的因素只有一个,就是寻道时间。

4.2.1 RAID 0技术详析

RAID 0是这样一种模式:我们拿5块盘的RAID 0为例子,如图4-7所示。

图4-8 虚拟磁盘

对外来说,参与形成RAID 0的各个物理盘会组成一个逻辑上连续、物理上也连续的虚拟磁盘。一级磁盘控制器(指使用这个虚拟磁盘的控制器,如果某台主机使用适配卡链接外部盘阵,则指的就是主机上的磁盘控制器)对这个虚拟磁盘发出的指令,都被RAID控制器收到并分析处理,根据Block映射关系算法公式转换成对组成RAID 0的各个物理盘的真实物理磁盘IO请求指令,收集或写入数据之后,再提交给主机磁盘控制器。

图4-8为一个RAID 0虚拟磁盘的示意图。

RAID 0还有另一种非条带化模式,即写满其中一块物理磁盘之后,再接着写另一块,直到所有组成的磁盘全部写满。这种模式对IO写没有任何优化,但是对IO读能提高一定的并发IO读几率。

下面我们来具体分析一个从上到下访问RAID 0磁盘的过程。

假如某一时刻,主机控制器发出指令:读取初始扇区10000长度128。

RAID控制器接受到这个指令之后,立即进行计算,根据对应公式(这个公式是RAID控制器在做逻辑条带化的时候制定的)算出10000号逻辑扇区所对应的物理磁盘的扇区号。

依次计算出逻辑上连续的下128个扇区所在物理磁盘的扇区号。

分别向对应这些扇区的磁盘再次发出指令。这次是真实的读取数据了,磁盘接受到指令,各自将数据提交给RAID控制器,经过控制器在Cache中的组合,再提交给主机控制器。

分析以上过程,发现如果这128个扇区都落在同一个Segment中的话,也就是说条带深度容量大于128个扇区的容量(64KB),则这次IO就只能真实地从这一块物理盘上读取,性能和单盘相比会减慢,因为没有任何优化,反而还增加了RAID控制器额外的计算开销。所以,在某种特定条件下要提升性能,让一个IO尽量扩散到多块物理盘上,就要减小条带深度。在磁盘数量不变的条件下,也就是减小条带大小(Stripe SIZE,也就是条带长度)。让这个IO的数据被控制器分割,同时放满一个条带的第一个Segment、第二个Segment等,依此类推,这样就能极大地占用多块物理盘。

误区: 总是以为控制器是先放满第一个Segment,再放满第二个Segment。

其实是同时进行的,因为控制器把每块盘要写入或者读取的数据都计算好了。如果这些目标磁盘不在相同的总线中,那么这种宏观“同时”的粒度将会更加细。因为毕竟计算机总线是共享的,一个时刻只能对一个外设进行IO。

所以,RAID 0要提升性能,条带做的越小越好。但是又一个矛盾出现了,就是条带太小,导致并发IO几率降低。因为如果条带太小,则每次IO一定会占用大部分物理盘,队列中的IO就只能等待这次IO结束后才能使用物理盘。而条带太大,又不能充分提高传输速度。这两个是一对矛盾,要根据需求来采用不同的方式。如果随机小块IO多,则适当加大条带深度;如果连续大块IO多,则适当减小条带深度。

接着分析RAID 0相对于单盘的性能变化。根据以上总结出来的公式,可以推出表4-1。

表4-1 RAID 0系统相对于单盘的IO对比

注:并发IO和IO SIZE/Stripe SIZE是一对矛盾,两者总是对立的。N=组成RAID 0的磁盘数目。系数=IO SIZE/Stripe SIZE和初始LBA地址所处的Stripe偏移综合系数,大于等于1。并发系数=并发IO的数量。

4.2.2 RAID 1技术详析

RAID 1是这样一种模式:拿两块盘的例子来进行说明,如图4-9所示。

图4-9 RAID 1系统示意图

RAID 1和RAID 0不同,RAID 0对数据没有任何保护措施,每个Block都没有备份或者校验保护措施。RAID 1对虚拟逻辑盘上的每个物理Block,都在物理盘上有一份镜像备份,也就是说数据有两份。对于RAID 1的写IO,速度不但没有提升,而且有所下降,因为数据要同时向多块物理盘写,时间以最慢的那个为准,因为是同步的。而对于RAID 1的读IO请求,不但可以并发,而且就算顺序IO的时候,控制器也可以像RAID 0一样,从两块物理盘上同时读数据,提升速度。RAID 1可以没有Stripe的概念,当然也可以有,同样可总结出表4-2。

表4-2 RAID 1系统相对于单盘的IO对比

注: N =组成RAID 1镜像物理盘的数目。

在读、并发IO的模式下,由于可以并发N个IO,每个IO占用一个物理盘,这就相当于提升了N倍的IOPS。由于每个IO只独占了一个物理盘,所以数据传输速度相对于单盘并没有改变,所以不管是随机还是顺序IO,相对单盘都不变。

在读、顺序IO、随机IO模式下,由于IO不能并发,所以此时一个IO可以同时读取N个盘上的内容。但是在随机IO模式下,寻道时间影响很大,纵使同时分块读取多个磁盘的内容,也架不住寻道时间的抵消,所以性能提升极小。

在读、顺序IO、连续IO模式下,寻道时间影响最低,此时传输速率为主要矛盾,同时读取多块磁盘的数据,时间减少为1/N,所以性能提升了N倍。

写IO的时候和读IO情况相同,就不做分析了。写IO因为要同时向每块磁盘写入备份数据,所以不能并发IO,也不能分块并行。但是如果控制器把优化算法做到极致的话,还是可以并发IO的,比如控制器从IO队列中提取连续的多个IO,可以将这些IO合并,并发写入磁盘,前提是这几个IO必须是事务性的,也就是说LBA必须连续,不然不能作为一个大的合并IO。而且和文件系统也有关系,文件系统碎片越少,并发几率越高。

4.2.3 RAID 2技术详析

RAID 2是一种比较特殊的RAID模式,它是一种专用RAID,现在早已被淘汰。它的基本思想是在IO到来之后,控制器将数据按照位分散开,顺序在每块磁盘中存取1b。这里有个疑问,磁盘的最小IO单位是扇区,有512B,如何写入1b?其实这个写入1b,并非只写入1b。我们知道上层IO可以先经过文件系统,然后才通过磁盘控制器驱动来向磁盘发出IO。最终的IO大小,都是N倍的扇区,也就是N×512B,N大于等于1,不可能发生N小于1的情况。即使需要的数据只有几个字节,那么也同样要读出或写入整个扇区,也就是512B。

明白这个原则之后,再来看一下RAID 2中所谓的“每个磁盘写1b”是个什么概念。IO最小单位为扇区(512B),我们就拿一个4块数据盘和3块校验盘的RAID 2系统为例给大家说明一下。这个环境中,RAID 2的一个条带大小是4b(1b×4块数据盘),而IO最小单位是一个扇区,那么如果分别向每块盘写1b,就需要分别向每块盘写一个扇区,每个扇区只包含1b有效数据,这显然是不可能的,因为太浪费空间,且没有意义。

下面以IO请求为例来说明。

写入“初始扇区10000长度1”,这个IO目的是要向LBA10000写入一个扇区的数据,也就是512B。

RAID 2控制器接受到这512B的数据后,在Cache中计算需要写入的物理磁盘的信息,比如定位到物理扇区,分割数据成比特。

然后一次性写入物理磁盘扇区。也就是说第一块物理盘,控制器会写入本次IO数据的第1、5、9、13、17、21等位,第二块物理盘会写入2、6、10、14、18、22等位,其他两块物理盘同样方式写入。

直到这样将数据写完。我们可以计算出来,这512B的数据写完之后,此时每块物理盘只包含128B的数据,也就是一个扇区的四分之一,那么这个扇区剩余的部分,就是空的。

为了利用起这部分空间,等下次IO到来之后,控制器会对数据进行比特分割,将数据填入这些空白区域。控制器将首先读出原来的数据,然后和新数据合并之后,一并再写回这个扇区,这样做效率和速度都大打折扣。其实RAID 2就是将原本连续的一个扇区的数据,以位为单位,分割存放到不连续的多块物理盘上,因为这样可以在任意条件下都迫使其全磁盘组并行读写,提高性能,也就是说条带深度为1位。这种极端看上去有点做得过火了,这也是导致它最终被淘汰的原因之一。

RAID 2系统中每个物理磁盘扇区其实是包含了N个扇区的“残体”。

思考: 那么如果出现需要更新这4个扇区中某一个扇区的情况,怎么办?

这种情况下,必须先读出原来的数据,和新数据合并,然后再一并写入。其实这种情况出现的非常少。我们知道上层IO的产生,一般是需要先经过OS的文件系统,然后才到磁盘控制器这一层的。所以磁盘控制器产生的IO一般都是事务性的,也就是这个IO中的所有扇区很大几率上对于上层文件系统来说是一个完整的事务,所以很少会发生只针对这个事务中某一个点进行读写的情况。

这样的话,每次IO就有很大几率都会包含入这些逻辑上连续的扇区,所以不必担心经常会发生那种情况。即便发生了,控制器也只能按照那种低效率的做法来做,不过总体影响较小。但是如果随机IO比较多,那么这些IO初始LBA,很有可能就会命中在一个两个事务交接的扇区处。这种情况就会导致速度和效率大大降低。连续IO出现这种情况的几率非常小了。

RAID 2因为每次读写都需要全组磁盘联动,所以为了最大化其性能,最好保证每块磁盘主轴同步,使同一时刻每块磁盘磁头所处的扇区逻辑编号都一致,并存并取,达到最佳性能。如果不能同步,则会产生等待,影响速度。

基于RAID 2并存并取的特点,RAID 2不能实现并发IO,因为每次IO都占用了每块物理磁盘。

RAID 2的校验盘对系统不产生瓶颈,但是会产生延迟,因为多了计算校验的动作。校验位和数据位是一同并行写入或者读取的。RAID 2采用汉明码来校验数据,这种码可以判断修复一位错误的数据,并且使用校验盘的数量太多,4块数据盘需要3块校验盘。但是随着数据盘数量的增多,校验盘所占的比例会显著减小。

RAID 2和RAID 0有些不同,RAID 0不能保证每次IO都是多磁盘并行,因为RAID 0的条带深度相对于RAID 2以位为单位来说是太大了。而RAID 2由于每次IO都保证是多磁盘并行,所以其数据传输率是单盘的N倍。为了最好地利用这个特性,就需要将这个特性的主导地位体现出来。

而根据IOPS=IO并发系数/(寻道时间+旋转延迟时间+数据传输时间),寻道时间比数据传输时间要大几个数量级。所以为了体现数据传输时间减少这个优点,就必须避免寻道时间的影响,而最佳做法就是尽量产生连续IO而不是随机IO。所以,RAID 2最适合连续IO的情况。另外,根据每秒IO吞吐量=IO并发系数×IO SIZE×V/(V×寻道时间×V×旋转延迟时间+IO SIZE),如果将IO SIZE也增大,则每秒IO吞吐量也将显著提高。所以,RAID 2最适合的应用就是产生连续IO、大块IO的情况。不言而喻,视频流服务等应用适合RAID 2。不过,RAID 2的缺点太多,比如校验盘数量多、算法复杂等,它逐渐被RAID 3替代了。表4-3比较了RAID 2系统与单盘的性能。

表4-3 RAID 2系统相对于单盘的IO对比

注: N =数据盘数量。RAID 2不能并发IO。

4.2.4 RAID 3技术详析

图4-10所示为一个RAID 3系统的条带布局图。

图4-10 RAID 3系统示意图

RAID 2缺点比较多,比如非事务性IO对它的影响、校验盘数量太多等。RAID 2的劣势就在于它将数据以比特为单位进行分割,将原本物理连续的扇区转变成物理不连续,而逻辑连续的。这样就导致了它对非事务性IO的效率低下。为了从根本上解决这个问题,RAID 3出现了。

既然要从根本上解决这个问题,首先就是需要抛弃RAID 2对扇区进行分散的做法,RAID 3保留了扇区的物理连续。RAID 2将数据以比特为单位分割,这样是为了保证每次IO占用全部磁盘的并行性。而RAID 3同样也保留了这个特点,但是没有以比特为单位来分散数据,而是以一个扇区或者几个扇区为单位来分散数据。RAID 3还采用了高效的XOR校验算法,但是这种算法只能判断数据是否有误,不能判断出哪一位有误,更不能修正错误。XOR校验使得RAID 3可以不管多少块数据盘,只需要一块校验盘就足够了。

RAID 3的每一个条带,其长度被设计为一个文件系统块的大小,深度随磁盘数量而定,但是最小深度为1个扇区。这样的话,每个Segment的大小一般就是1个扇区或者几个扇区的容量。以图4.10的例子来看,有4块数据盘和1块校验盘。每个Segment也就是图中的一个Block Portion,假如为两个扇区大小,就是1KB,则整个条带的数据部分大小为4KB。如果一个Segment大小为8个扇区,即4KB,则整个条带大小为16KB。

例解:RAID 3的作用机制

还是用一个例子来说明RAID 3的作用机制。一个4块数据盘和1块校验盘的RAID 3系统,Segment SIZE为两个扇区大小(1KB),条带长度为4KB。

RAID 3控制器接收到了这样一个IO:“写入初始扇区10000 长度8”,即总数据量为8×512B=4KB。

控制器先定位LBA10000所对应的真实物理LBA,假如LBA10000恰好在第一个条带的第一个Segment的第一个扇区上,那么控制器将这个IO数据里的第1、2个512B写入这个扇区。

同一时刻,第3、4个512B会被同时写入这个条带的第二个Segment中的两个扇区,其后的数据同样被写入第3、4个Segment中,此时恰好是4KB的数据量。也就是说这4KB的IO数据同时被分散写入了4块磁盘,每块磁盘写入了两个扇区,也就是一个Segment。它们是并行写入的,包括校验盘也是并行写入的,所以RAID 3的校验盘没有瓶颈,但是有延迟,因为增加了计算校验的开销。

但现代控制器一般都使用专用的XOR硬件电路而不是CPU来计算XOR,这样就使得延迟降到最低。上面那种情况是IO SIZE刚好等于一个条带大小的时候,如果IO SIZE小于一个条带大小呢?

还是刚才那个环境,此时控制器接收到IO大小为2KB的写入请求,也就是4个连续扇区,那么控制器就只能同时写入两个磁盘了,因为每个盘上的Segment是两个扇区,也只能得到两倍的单盘传输速率。同时为了更新校验块,写惩罚也出现了。但是如果同时有个IO需要用到另外两块盘,那么恰好可以和当前的IO合并起来,这样就可以并发IO,这种相邻的IO一般都是事务性的连续IO。

再看看IO SIZE大于条带长度的情况。还是那个环境,控制器收到的IO SIZE为16KB。则控制器一次所能并行写入的是4KB,这16KB就需要分4批来写入4个条带。其实这里的分4批写入,不是先后写入,而是同时写入,也就是这16KB中的第1、5、9、13KB将由控制器连续写入磁盘1,第2、6、10、14KB,连续写入磁盘2,依此类推。直到16KB数据全部写完,是并行一次写完。这样校验盘也可以一次性计算校验值并且和数据一同并行写入,而不是“分批”。

通过比较,我们发现,与其使IO SIZE小于一个条带的大小,从而空闲出一些磁盘,不如使IO SIZE大于或者等于条带大小,取消磁盘空余。因为上层IO SIZE是不受控的,控制器说了不算,但是条带大小是控制器说了算的。所以如果将条带大小减到很小,比如两个扇区、一个扇区,则每次上层IO一般情况下都会占用所有磁盘进行并发传输。这样就可以提供和RAID 2一样的传输速度,并避免RAID 2的诸多缺点。RAID 3和RAID 2一样不能并发IO,因为一个IO要占用全部盘,就算IO SIZE小于Stripe SIZE,因为校验盘的独享也不能并发IO。

思考: 一般来说,RAID3的条带长度=文件系统块大小。这样,就不会产生条带不对齐的现象,从而避免产生碎片。

虽然纯RAID 3系统不能并发IO,但是可以通过巧妙的设计,形成RAID 30系统。如果文件系统块为4KB,则使用8块数据盘+2块校验盘做成的RAID 30系统,便可以并发2个IO了。表4-4比较了RAID 3系统与单盘的性能。

表4-4 RAID 3系统相对于单盘的IO对比

注: N =组成RAID 3的数据磁盘数量。和RAID 2相同,事务性连续IO可能并发。

和RAID 2一样,RAID 3同样也是最适合连续大块IO的环境,但是它比RAID 2成本更低,更容易部署。

不管任何形式的RAID,只要是面对随机IO,其性能与单盘比都没有大的优势,因为RAID所做的只是提高传输速率、并发IO和容错。随机IO只能靠降低单个物理磁盘的寻道时间来解决。而RAID不能优化寻道时间。所以对于随机IO,RAID 3也同样没有优势。

而对于连续IO,因为寻道时间的影响因素可以忽略,RAID 3最拿手了。因为像RAID 2一样,RAID 3可以大大加快数据传输速率,因为它是多盘并发读写。所以理论上可以相当于单盘提高N倍的速率。

但是RAID 3最怕的就是遇到随机IO。由于在RAID 3下,每个IO都需要牵动所有盘来为它服务,这样的话,如果向RAID 3组发送随机IO,那么所有磁盘均会频繁寻道,此时,整个RAID组所表现出来的性能甚至不如单盘,因为就算组内有100块盘,由于随机IO的到来,所有磁盘均忙于寻道,100块盘并发寻道所耗费的时间与一块盘是相同的。

4.2.5 RAID 4技术详析

图4-11是一个RAID 4系统的条带布局图。

图4-11 RAID 4系统示意图

不管是RAID 2还是RAID 3,它们都是为了大大提高数据传输率而设计,而不能并发IO。诸如数据库等应用的特点就是高频率随机IO读。想提高这种环境的IOPS,根据公式IOPS=IO并发系数/(寻道时间+旋转延迟时间+数据传输时间),随机读导致寻道时间和旋转延迟时间增大,靠提高传输速率已经不是办法。所以观察这个公式,想在随机IO频发的环境中提高IOPS,唯一能够做的是要么用高性能的磁盘(即平均寻道时间短的磁盘),要么提高IO并发系数。不能并发IO的,想办法让它并发IO。并发系数小的,想办法提高系数。

思考: 在RAID 3的基础上,RAID 4被发展起来。我们分析RAID 3的性能的时候,曾经提到过一种情况,就是IO SIZE小于Stripe SIZE的时候,此时有磁盘处于空闲状态。如果抓住这个现象,同时让队列中的其他IO来利用这些空闲的磁盘,岂不是正好达到并发IO的效果了么?所以RAID 4将一个Segment的大小做得比较大,以至于平均IO SIZE总是小于Stripe SIZE,这样就能保证每个IO少占用磁盘,甚至一个IO只占用一个磁盘。

是的,这个思想对于读IO是对路子的,但是对于写IO的话,有一个很难克服的问题,那就是校验盘的争用。考虑一下这样一种情况,在4块数据盘和1块校验盘组成的RAID 4系统中,某时刻一个IO占用了前两块盘和校验盘,此时虽然后两块是空闲的,可以同时接受新的IO请求。但是接受了新的IO请求,则新IO请求同样也要使用校验盘。由于一块物理磁盘不能同时处理多个IO,所以新IO仍然要等旧IO写完后,才能写入校验。这样就和顺序IO没区别了。数据盘可并发而校验盘不可并发,这样不能实现写IO并发。

如果仅仅根据争用校验盘来下结论说RAID 4不支持并发IO,也是片面的。我们可以设想这样一种情形,某时刻一个IO只占用了全部磁盘的几块盘,令一些磁盘空闲。如果此时让队列中下一个IO等待的话,那么当然不可能实现并发IO。

思考: 如果队列中有这样一个IO,它需要更新的LBA目标和正在进行的IO恰好在同一条带上,并且处于空闲磁盘,还不冲突,那么此时我们就可以让这个IO也搭一下正在进行的IO的顺风车。反正都是要更新这个条带的校验Segment,与其两个IO先后更新,不如让它们同时更新各自的数据Segment,而控制器负责计算本条带的校验块。这样就完美的达到了IO并发。

但是,遇到这种情况的几率真是小之又小。即便如此,控制器如果可以对队列中的IO目标LBA进行扫描,将目标处于同一条带的IO,让其并发写入,这就多少类似NCQ技术了。但是如果组合动作在上层就已经算好了,人为的创造并发条件,主动去合并可以并发的,合并好之后再下发给下层,那么事务并发IO的几率将大大增加,而不是靠底层碰运气来实现,不过此时称为“并发事务”更为合适。

所谓“上层”是什么呢?上层就是一级磁盘控制器驱动程序的上层,也就是文件系统层。文件系统管理着底层磁盘,决定数据写往磁盘或者虚拟卷上的哪些块。所以完全可以在文件系统这个层次上,将两个不同事务的IO写操作,尽量放到相同的条带上。比如一个条带大小为16KB,可以前8KB放一个IO的数据,后8KB放另一个IO的数据,这两个IO在经过文件系统的计算之后,经由磁盘控制器驱动程序,向磁盘发出同时写入整个条带的操作,这样就构成了整条写。如果实在不能占满整条,那么也应该尽量达成重构写模式,这样不但并发了IO,还使得写效率增加。

提示: 这种在文件系统专门为RAID 4做出优化的方案,最典型的就是NetApp公司著名的WAFL文件系统。WAFL文件系统的设计方式确保了能够最大限度地实现整条写操作。

图4-12对比显示了WAFL如何分配同样的数据块,从而使得RAID 4更加有效。WAFL总是把可以合并写入的数据块尽量同时写到一个条带中,以消除写惩罚,增加IO并发系数。相对于WAFL,左边的FFS(普通文件系统)由于对RAID 4没有感知,产生的IO不适合RAID 4的机制,从而被零散地分配到了6个独立的条带,因此致使6个校验盘块需要更新,而只能顺序的进行,因为校验盘不可并发。而右边的WAFL仅仅使用3道条带,只有3个校验块需要更新,从而大大提高了性能。表4-5比较了RAID 4系统与单盘的性能。

图4-12 普通文件系统与WAFL文件系统的对比

表4-5 RAID 4系统相对于单盘的IO对比

注: N 为RAID 4数据盘数量。IO SIZE/Stripe SIZE太大则并发IO几率很小。

注意: 如果IO SIZE/Stripe SIZE的值太小,那么顺序IO读不管是连续还是随机IO几乎都没有提升。顺序IO写性能下降,是因为IO SIZE很小,又是顺序IO,只能进行读改写,性能会降低不少。

所以,如果要使用RAID 4,不进行特别优化是不行的,至少要让它可以进行并发IO。观察表4-5可知,并发IO模式下性能都有所提升。然而如果要优化到并发几率很高,实在不容易。目前只有NetApp的WAFL文件系统还在使用RAID 4,其他产品均未见使用。RAID 4面临淘汰,取而代之的是拥有高盲并发几率的RAID 5系统。所谓盲并发几率,就是说上层不必感知下层的结构,即可增加并发系数。

4.2.6 RAID 5技术详析

图4-13为一个RAID 5系统的条带布局图。

图4-13 RAID 5系统示意图

先介绍几个概念:整条写、重构写与读改写。

(1)整条写(Full-Stripee Write): 需要修改奇偶校验群组中所有的条带单元,因此新的XOR校验值可以根据所有新的条带数据计算得到,不需要额外的读、写操作。因此,整条写是最有效的写类型。整条写的例子,如RAID 2、RAID 3。它们每次IO总是几乎能保证占用所有盘,因此每个条带上的每个Segment都被写更新,所以控制器可以直接利用这些更新的数据计算出校验数据之后,在数据被写入数据盘的同时,将计算好的校验信息写入校验盘。

(2)重构写(Reconstruct Write): 如果要写入的磁盘数目超过阵列磁盘数目的一半,可采取重构写方式。在重构写中,从这个条带中不需要修改的Segment中读取原来的数据,再和本条带中所有需要修改的Segment上的新数据一起计算XOR校验值,并将新的Segment数据和没有更改过的Segment数据以及新的XOR校验值一并写入。显然,重构写要牵涉更多的I/O操作,因此效率比整条写低。重构写的例子,比如在RAID 4中,如果数据盘为8块,某时刻一个IO只更新了一个条带的6个Segment,剩余两个没有更新。在重构写模式下,会将没有被更新的两个Segment的数据读出,和需要更新的前6个Segment的数据计算出校验数据,然后将这6个Segment连同校验数据一并写入磁盘。可以看出,这个操作只是多出了读两个Segment中数据的操作和写Parity校验数据的操作,但是写的时候几乎不产生延迟开销,因为是宏观同时写入。

(3)读改写(Read-Modify Write): 如果要写入的磁盘数目不足阵列磁盘数目的一半,可采取读改写方式。读改写过程是:先从需要修改的Segment上读取旧的数据,再从条带上读取旧的奇偶校验值;根据旧数据、旧校验值和需要修改的Segment上的新数据计算出这个条带上的新的校验值;最后写入新的数据和新的奇偶校验值。这个过程中包含读取、修改和写入的一个循环周期,因此称为读改写。读改写计算新校验值的公式为:新数据的校验数据=(老数据EOR新数据)EOR老校验数据。如果待更新的Segment已经超过了条带中总Segment数量的一半,则此时不适合用读改写,因为读改写需要读出这些Segment中的数据和校验数据。而如果采用重构写,只需要读取剩余不准备更新数据的Segment中的数据即可,而后者数量比前者要少。所以超过一半用重构写,不到一半用读改写,整条更新就用整条写。

写效率排列为:整条写>重构写>读改写。

图4-14是RAID 5系统的三种写模式示意图。

图4-14 RAID 5写模式示意图

为了解决RAID 4系统不能并发IO的窘境,RAID 5相应而出。RAID 4并发困难是因为它的校验盘争用的问题,如果能找到一种机制可以有效地解决这个问题,则实现并发就会非常容易。RAID 5恰恰解决了校验盘争用这个问题。RAID 5采用分布式校验盘的做法,将校验盘打散在RAID组中的每块磁盘上。如图4-13所示,每个条带都有一个校验Segment,但是不同条带中其位置不同,在相邻条带之间循环分布。为了保证并发IO,RAID 5同样将条带大小做得较大,以保证每次IO数据不会占满整个条带,造成队列中其他IO的等待。所以,RAID 5要保证高并发率,一旦某时刻没有成功进行并发,则这个IO几乎就是读改写模式,所以RAID 5拥有较高的写惩罚。

但是在随机写IO频发的环境下,由于频发的随机IO提高了潜在的并发几率,如果碰巧并发的IO同处一个条带,还可以降低写惩罚的几率。这样,RAID 5系统面对频发的随机写IO,其IOPS下降趋势比其他RAID类型要平缓一些。

来分析一下RAID 5具体的作用机制。以图4-13的环境为例,条带大小80KB,每个Segment大小16KB。

某一时刻,上层产生一个写IO:写入初始扇区10000长度8,即写入4KB的数据。控制器收到这个IO之后,首先定位真实LBA地址,假设定位到了第1个条带的第2个Segment(位于图中的磁盘2)的第1个扇区(仅仅是假设),则控制器首先对这个Segment所在的磁盘发起IO写请求,读取这8个扇区中原来的数据到Cache。

与此同时,控制器也向这个条带的校验Segment所在的磁盘(即图中的磁盘1)发起IO读请求,读出对应的校验扇区数据并保存到Cache。

利用XOR校验电路来计算新的校验数据,公式为:新数据的校验数据=(老数据EOR新数据)EOR老校验数据。现在Cache中存在:老数据、新数据、老校验数据和新校验数据。

控制器立即再次向相应的磁盘同时发起IO写请求,将新数据写入数据Segment,将新校验数据写入校验Segment,并删除老数据和老校验数据。

在上述过程中,这个IO占用的始终只有1、2两块盘,因为所要更新的数据Segment对应的校验Segment位于1盘,自始至终都没有用到其他任何磁盘。如果此时队列中有这么一个IO,它的LBA初始目标假如位于图4-13中下面方框所示的数据Segment中(磁盘4),IO长度也不超过Segment的大小。而这个条带对应的校验Segment位于磁盘3上。这两块盘未被其他任何IO占用,所以此时控制器就可以并发的处理这个IO和上方红框所示的IO,达到并发。

RAID 5相对于经过特别优化的RAID 4来说,在底层就实现了并发,可以脱离文件系统的干预。任何文件系统的IO都可以实现较高的并发几率,又称为盲并发。而不像基于WAFL文件系统的RAID 4,需要在文件系统上规划计算出并发环境。然而就效率来说,仍然是WAFL拥有更高的并发系数,因为毕竟WAFL是靠主动创造并发,而RAID 5却是做好了陷阱等人往里跳,抓着一个是一个。

RAID 5磁盘数量越多,可并发的几率就越大。表4-6比较了RAID 5与单盘的性能。

表4-6 RAID 5系统相对于单盘的IO对比

续表

注:RAID 5最适合小块IO。并发IO的情况下,性能都较单盘有所提升。

图4-15为一个RAID 5E系统的条带布局图。

图4-15 RAID 5E系统示意图(HS代表HotSpare)

图4-16则为一个RAID 5EE系统的条带布局图。

图4-16 RAID 5EE系统示意图

4.2.7 RAID 6技术详析

图4-17为一个RAID 6系统的条带布局图。

图4-17 RAID 6系统示意图

RAID 6之前的任何RAID级别,最多能保障在坏掉一块盘的时候,数据仍然可以访问。如果同时坏掉两块盘,则数据将会丢失。为了增加RAID 5的保险系数,RAID 6被创立了。RAID 6比RAID 5多增加了一块校验盘,也是分布打散在每块盘上,只不过是用另一个方程式来计算新的校验数据。这样,RAID 6同时在一个条带上保存了两份数学上不相关的校验数据,这样能够保证同时坏两块盘的情况下,数据依然可以通过联立这两个数学关系等式来求出丢失的数据。RAID 6与RAID 5相比,在写的时候会同时读取或者写入额外的一份校验数据。不过由于是并行同时操作,所以不比RAID 5慢多少。其他特性则和RAID 5类似。

表4-6比较了RAID 6与单盘的性能。

表4-7 RAID 6系统相对于单盘的IO对比 /P+kGoH82ZVv9D6rLbGCG71Ujf2yP55QXVETL1d5ZhjQlZfxEQZZ8tWz5eXytqXX

点击中间区域
呼出菜单
上一章
目录
下一章
×