Chinaunix首页 | 论坛 | 博客
  • 博客访问: 160556
  • 博文数量: 17
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 342
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-19 11:38
个人简介

A ZFS fan

文章分类
文章存档

2014年(17)

分类: 服务器与存储

2014-06-19 22:13:41


1. inexpensive VS independent


1.1 传统的RAID - Redundant arrary of independent disks

从概念来看,RAID的最初目的是利用多个廉价的(inexpensive)磁盘来构成磁盘阵列,提高磁盘空间,平衡低速磁盘与高速CPU之间的关系,以及提高数据的安全性。在实际的实现过程中,RAID确实做到了“提高数据的安全性”,也通过多个磁盘并发的吞吐量,大大提高了磁盘的读写性能,但是却没能达到之前“inexpensive”的目标。拿RIAD5来说,更新数据分为三个步骤:读取数据 - 修改数据 - 修改校验值。在修改数据与修改校验值之间,一旦发生宕机、断电等现象,那么数据和校验值之间就会产生不一致,而且这种不一致将永远无法修复。为了解决之一问题,RAID使用了高昂的硬件来防止RAID在断电时发生错误——但是这样,就不那么 inexpensive了。于是乎,RAID中的inexpensive被替换成了independent - 独立的。RAID(Redundant arrary of independent disk)

1.2 RAIDZ- Redundant arrary of inexpensive disks

ZFS还原了RAID中的inexpensive,ZFS使用Copy-On-Write + 事务处理技术,很好地解决了写数据与写校验数据之间可能发生故障的问题。而且ZFS的RAIDZ无需任何额外的硬件支撑,真正意义上还原了RAID inexpensive的目标。


2. 三奇偶校验


2.1 三奇偶校验概念

ZFS RAIDZ的奇偶校验采用了“Reed-Solomon Coding”,简单来说就是一份数据可以被分成N份,这N份的数据又可以产生M份的checksum,这样就会有N+M份数据,其中的任何M份数据损坏都可以通过剩余的数据来恢复。详细可以参考论文A tutorial on Reed-Solomon coding for fault-tolerance in RAID-like systems》。RAID5就是采用了单奇偶校验(M=1,允许一个磁盘损坏,系统可以正常访问磁盘数据),RAID6采用双奇偶校验按(M=2,允许两个磁盘损坏,系统正常访问磁盘上的数据)。


ZFS中提供了最高三奇偶校验。
     单奇偶校验RAID-Z, 即raidz或raidz1, 类似于RAID5
     双奇偶校验RAID-Z, 即raidz2,类似于RAID6
     三奇偶校验RAID-Z, 即raidz3

2.2 ZFS中三奇偶校验实现

ZFS中,三份校验值并不是简单的复制,三个校验都采用了不同的算法。下面用P、Q、R分别代表三份校验值。
假设,将一份数据被分成N份,D0,D1,…… Dn-2,Dn-1
       P:简单做异或操作
         P = D0 + D1 + …… + Dn-2 + Dn-1
      Q:Q = 2n-1 * D0 + 2n-2 * D1 +  ……  + 21 * Dn-2 + 20 * Dn-1
      R:R = 4n-1 * D+ 4n-2 * D+  ……  + 41 * Dn-2 + 40 * Dn-1

P,Q表达式可以写成下面的形式
    Q = 2n-1 * D+ 2n-2 * D+  ……  + 21 * Dn-2 + 20 * Dn-1
        = ((...((D0) *2 + D1) * 2 + ...) * 2 + Dn-2) * 2 + Dn-1
     R = 4n-1 * D+ 4n-2 * D+  ……  + 41 * Dn-2 + 40 * Dn-1
        = ((...((D0) *4 + D1) * 4 + ...) * 4 + Dn-2) * 4 + Dn-1

需要注意的是,这里的操作是基于GF(Galois Field)定义的运算。所以,这里的“+”操作表示异或,"*2"操作在C语言中可以这么写:((a << 1) ^ (a & 0x80) ? 0x1d : 0)。关于Galois Field的详细说明自己搜索一下吧~

于是,ZFS的源码定义这样两个宏,这样"*2"和"*4"操作都可以通过简单的位操作来实现。

点击(此处)折叠或打开

  1. #define    VDEV_RAIDZ_MUL_2(x)    (((x) << 1) ^ (((x) & 0x80) ? 0x1d : 0))
  2. #define    VDEV_RAIDZ_MUL_4(x)    (VDEV_RAIDZ_MUL_2(VDEV_RAIDZ_MUL_2(x)))


3. 动态条带化

传统的RAID中条带化的宽度是固定的。加入新的设备之后需要重新设置条带化宽度。而对于ZFS则不是。ZFS采用了Copy-On-Write技术,每次在写入数据的时候都会充分利用当前存储池中的磁盘带宽以达到效率的最大化。在存储池中加入新的磁盘之后,ZFS会自动调整条带化的宽度,利用新设备的带宽。


阅读(4708) | 评论(0) | 转发(0) |
0

上一篇:ZFS 阶段小结

下一篇:ZIL(ZFS Intent Log)

给主人留下些什么吧!~~