前几天我的一个同事在对计划采购的存储进行测试,期间聊到了raid5的话题,我和他的意见产生了分歧。他的说法是raid5不能挂太多盘是因为如果挂太多盘写惩罚会非常严重导致性能下降。而我的观点则是对于raid5来说,磁盘越多性能越好,不能挂太多盘是因为容错性下降的原因。


首先,先明确raid5的写惩罚是怎么一回事。我们都知道raid5的特点是N+1的冗余方式,N越大,冗余度越低,而且我们也都知道raid5会把校验信息打散在各个磁盘。这么做的目的当然不是为了好玩,而是为了避免出现校验盘争用的现象。

raid3采用的校验盘放在一起,当两个命令同时对磁盘进行操作的时候,就需要同时操作校验条带。如果这两个操作不属于同一个条带。那么这两个操作就不能同时进行,也就是出现了校验盘争用的现象导致了校验盘瓶颈。


现在问题来了,raid5是如何写入数据的,这个问题直接决定了写惩罚的原理。

raid5的写入情况分成3种:

1.要写入的数据布满整个条带。这种情况可以把要写入的数据的校验信息算好,直接把整个条带写入磁盘。

2.要写入的数据大于半个条带。这种情况可把这个条带上不需要修改的数据读出来,和要写入的数据一起计算校验,并写入磁盘

3.要写入的数据小于半个条带。这种情况需要把要修改的旧数据和原始的校验数据读出来,并连同新数据一起计算校验值。

计算公式是 新校验= 老数据 XOR 新数据 XOR 老校验

证明比较简单:

假设原来的校验c=i[0] xor i[1] xor i[2]....xor i[n]

我要把i[0]修改为i1[0],那么c1=i1[0] xor i[1]....xor i[n]

因为 1 xor 0=1  0 xor 0=0 因此 i xor 0=i

得出 c1=i1[0] xor i[1]...xor i[n] xor 0

我们把0换成i[0] xor i[0],c1=i1[0] xor i[1]..xor i[n] xor (i[0] xor i[0])

因为xor 满足结合律,所以c1=x1[0] xor i[0] xor (i[0] xor i[1]...xor i[n])=x1[0] xor x[0] xor c

这个计算公式得到的结论是,在我写入一个segment的时候,不管这个raid有多少块盘组成,我只需要操作两个盘。一个是校验盘,一个是要写入的磁盘。对于这两块盘操作是并发的,可以同时进行。而写惩罚的意义,就在于我需要先把数据读出来,再写入。

正因为如此,在有n块盘的时候,想在不同条带下同时写入数据的并发成为可能。当然前提是每个随机数据并不要太大,占据大部分条带。对于典型的随机读写数据来说,4k是一个比较常见的大小,而raid5的条带深度往往大于4k。因此可以保证每个随机读写都占据了一个segment。在这种情况下可以想象,最大的并发数量是n/2,即每个数据的数据和校验同另外一个数据和校验的segment所处的磁盘都不同。而增加磁盘就相当于增大并发的峰值或者增大并发的概率。这个是单凭直觉就能想到的。因此不管原来有多少块盘,增加磁盘的数量对于随机写来说始终是有利的。

对于大块连续写入,因为都是整个条带写入,n值的升高更能提高写入效率,而不需要考虑概率的影响。



但问题来了,raid5随机写增加磁盘和并发概率提升的关系是什么?


我先假设我们使用n个磁盘组成的raid5,我们在假设每个磁盘所拥有的条带数量为m。

那么segment在整个raid5卷中的数据排布可以看成是一个m*n的矩阵,我们用A来表示。

我不了解raid5校验seg具体的排布方式,大概不同控制器会根据统计规律有所优化,但是有一点可以猜到的是,校验seg在n个磁盘中是均匀分布的。那么我们假设分布规律是每层条带向右移动一个磁盘,到最后一个磁盘后循环。如果其他分布情况,我可以通过矩阵的行交换把那个矩阵变成我这个矩阵,同时不会影响到并发的概率。

在这种情况下,我们以segment为单位给整个磁盘能用的地址编址,能够使用的地址是(n-1)*m,而校验所占用的空间大小为m。

我们假设我们要访问或者插入的seg在能用的seg 里面编址为x。

把x在矩阵中的位置A[i][j]做映射。

因为每层seg只有一个校验seg,所以这个层的层号i=x/(n-1) 。        (向下取整除)

根据层号i,可以计算出这个条带校验seg所在的j_c=i%n                   (mod操作)

在没进行交换前,数据seg所在的磁盘为j_r=x%(n-1)。再看j是在对角线的左侧或是右侧,根据这个确定他在矩阵中的位置。

if j_r<j_c:

       j=j_r

else:

      j=j_r+1


如果计算并发概率,我只需要按照经典概率的方法,分析每次插入时候,能够不产生冲突的插入种类,比上总共插入的总类,就可以得到至少n次并发概率的公式。但是如果这么计算的话公式会非常复杂。

因为每次插入不仅要考虑要插入的数据不应该在已经插入的数据的数据和校验的位置。还要考虑新插入的数据的校验的位置以及校验信息所在的位置,因为这个位置是不能插入数据的。当然还要考虑插入在同一层条带的概率。

试了几次,自己都绕糊涂了。

于是咱们换种办法。我不考虑这些插入的数据会查到统一层条带的可能性。这是因为m的值要远大于n。即使raid5的条带深度可以很深,但是跟磁盘的大小比起来还是差太多。能够插到同一个条带的可能性还是非常小的。除非插入的序列数量成一定规模。

二是我假设m是n的整数倍,那么m*n的矩阵可以变成m/n个n*n方阵,这些矩阵的对角线都是校验数据。

首先需要考虑的是m的值和并发的概率是否有关。当然m值很小的情况下,肯定有关,因为分布到同一层条带的概率非常大,但是这种情况我们不考虑。那么我可以假设我在原始的矩阵下再增加一个方阵。原来方阵因为插入排除掉的插入的可能会同样复制到这个方阵内。因此m的增加并不能影响并发的概率。那么我们就把多余的方阵去掉,只留下一个n*n方阵分析。

但是分析这个方阵,我们就要分析两个插入的数据是否在同一行或者是同一列。如果是,说明产生了争用冲突。之所以分析同一行,而不把他排除掉是因为这个同一行并不表示i_1==i_2,而是i_1==i_2%n,即表示校验冲突的情况。如果我们要真正考虑同一行产生的影响。因为假设插入的数据是在全部空间里均匀分布的,只需要把这同一行再乘以1/m就行了。



这样,我们直接把不用的对角线去掉,因为这部分表示不能使用的校验的位置。

变成了一个n*(n-1)矩阵。

那么插入k个数据不产生冲突就相当于在n*(n-1)的矩阵中取k个点,这些点的行和列都互不相等。

等于行不相等的概率乘以列不相等的概率。其中,k<=n/2

总的概率等于(n-i/n) i从0到k-1的连乘再乘以[(n-i-1)/(n-1)] i从0到k-1的连乘

实际上等于(c(n,k)/n^k)*(c(n-1,k)/(n-1)^k)

分析大概推导过程是这样的。

(昨天有点犯糊涂了,最后推导的时候逻辑产生了错误。修改一下。)

虽然看起来概率并不大,但是可以把一定深度的写入队列重新进行排队来构造一个并发。把在线算法转换成离线算法。根据我的直觉在均匀分布的情况下猜测能够构造并发的可能性还是很大的,就不证明了。