什么是 RAID

通常,存储企业级数据有两种刚需:

  • 数据保护

    当存储介质发生某种程度损坏时,存储方案应该有能力恢复大部分数据;

  • 高性能读写

    存储方案应该对客户提供尽可能快的读写服务。

基于以上两个需求,RAID(Redundant Array of Independent Disk)提供一种应用广泛的解决方案。

简而言之,RAID 以某种算法将数据冗余存储到多块磁盘上,并内部嵌入高性能 DRAM 缓存来保障读写速率。由于它是冗余保存数据,所以当磁盘发生某种意外导致数据损毁时,RAID 都可在其损毁范围内恢复数据,恢复的程度取决于损毁程度和数据冗余算法。其实,对于大多数开发者来说,RAID 对外也是抽象成一个具有标准接口(比如 PCIE)的磁盘设备。

RAID 的不同存储方案

  • RAID0

  • RAID1

  • RAID2

  • RAID3

  • RAID4

  • RAID5

  • RAID6

组合模式

影响磁盘性能的几个关键因素

write-through 和 write-back

RAID 设备中通常都前置了一个 DRAM 缓存,这就导致写操作会有两种不同的模式:

  • write-through (写穿)

    数据先写入到 DRAM 缓存,然后再写入磁盘,直到数据被完全写入到磁盘后,RAID 控制器才认为写操作完成;

  • write-back (写回)

    只要数据写入到 DRAM 缓存,RAID 控制器就认为写入操作完成,而 DRAM 缓存的数据会异步写入磁盘;

其实,我们可以认为 write-through 模式是同步写磁盘,而 write-back 模式是异步写磁盘

很明显,write-through 模式较 write-back 模式要慢,因为它必须等待磁盘成功写入后才返回。而且,write-back 模式可能会导致数据丢失。假如某次处于 write-back 模式的写操作突然遭遇断电,DRAM 因断电而停止刷新操作,那么此次写操作的数据就彻底丢失了。

为了解决这个问题,某些 RAID 设备会在 DRAM 旁加上电池来防止此类情况。当发生突然断电时,DRAM 旁的电池可继续为 DRAM 供电,让 DRAM 处于一种「低电量自刷新模式」(low-power self-refresh mode),从而维持数据的存储。

这种解决方案有很多局限性

  • DRAM 缓存依赖于电池来提供能源,而电池同样会面临突然断电的情况。不像普通的电源供电,电池的电量在一定时间段内是有限且逐渐递减的。当电池电量耗尽时,DRAM 缓存同样无法保存数据;

  • 如果想要加长断电后数据维持时间或加大 DRAM 缓存容量,电池的容量也必须同步加大。但是电池容量的加大又会导致其它问题,比如电池体积增大,单次充电时间加长(充电之时 RAID 设备也不能使用 write-back 写模式)等;

  • DRAM 缓存将被电池一直拴着。假如我们此时想将断电后靠电池维系供电的 DRAM 缓存做数据迁移,我们必须保证电池与 DRAM 一直处于连接状态。从硬件设计角度来看,我们必须将 RAID 控制器和电池放置在一个单一连接单元中。这对数据迁移带来了很多不便。

什么是 NVCache

从上文关于 write-through 和 write-back 模式的讨论中,我们知道处于 write-back 写模式下数据有可能会因断电而丢失。为了解决这个问题,RAID 设备可以内置一个非易失的闪存设备(non-volatile flash memory),并用锂电池为该设备供电,让它可以在断电之时能够将 DRAM 缓存的数据转移到闪存中。当电力重新恢复后,之前 DRAM 中的缓存数据可以通过闪存来恢复。这种方法就称为 Cache-to-Flash Non-volatile Cache,或简称为 CTF NVCache,下文称 NVCache。

NVCache 的运行原理

目前 NVCache 方案多数采用的是 SSDs(Solid State Disk Drives)。图 1 是 Dell 某个 RAID 设备的电路逻辑图:

其中,发生突然掉电后数据迁移的过程可以概括为:

  • 普通情况下,缓存数据存储于 DRAM 存储阵列中;

  • FPGA(Field Programmable Gate Array)模块会监测系统电源,当发生突然掉电时,它会将 DRAM 缓存数据转移到 Flash 存储上。整个数据迁移过程通过电池(有些方案采用超大容量电容)来提供电源。当迁移完成后,Flash 中的数据可以无需供电即可继续存储;

  • 当电力恢复后,FPGA 模块通过 Flash 存储中的数据重建 DRAM 缓存并通知 RAID 控制器有数据需要写入到磁盘中;

我们可以认为 FPGA 模块是整个 CTF 过程的控制单元,而 FPGA 模块本身的状态则通过 I2C 总线受控于RAID 控制器。FPGA 模块连接着 DRAM 数据总线和 NVCache 模块,通过以下几种控制信号来控制 CTF 过程:

  • NVCache Ready:由 FPGA 模块输出,用以指示 NVCache 子系统可以进入 write-back 写模式。

  • DRAM Available:由 FPGA 模块输出给 RAID 控制器,用以指示 RAID 控制器当前可对 DRAM 存储阵列进行读写操作。

  • NVCache Enable:由 RAID 控制器输出给 FPGA 模块,用以指示系统已进入 write-back 写缓存模式,RAID 控制将开始把缓存数据写入 DRAM 存储阵列中。

  • Cache Dirty:由 FPGA 模块输出给 RAID 控制器,用以指示系统已进入 non-volatile 模式,DRAM 缓存中的数据已失效。

  • NVCache PG:由 RAID 子系统输出给 FPGA 模块,用以指示 NVCache 子系统的供电情况正常(Power Good)。

NVCache 的状态变迁

FPGA 模块作为 CTF 过程的控制单元,其控制逻辑可以汇总成一系列的有限状态机(finite state machine)。FPGA 模块通过控制信号来控制 NVCache 子系统的状态变迁,它主要有以下几种状态:

  • Power Up

  • Idle

  • Backup

  • Glitch

  • Erase

  • Restore

  • Power Down

整个状态变迁逻辑可如图 2 所示:

NVCache 在 Raft 算法分布式存储上的应用

从上文的描述可以看出,NVCache 是在原来 RAID 的基础上增加了一层高可用的保护,在不丢失数据的前提下可以大幅提升写入性能(写缓存)。

Raft 算法中最为核心当属日志,所谓的一致性其实本质上是维护各个节点上日志的一致性。如果大多数节点日志丢失,则当前集群将无法恢复。所以,此时可以考虑使用 NVCache 的 RAID,即可以提升数据保存的可靠性,又可以提升性能(比如 etcd 的性能其实就是受限于 fsync())。

参考文献