非易失内存NVM一致性(Consistency)问题研究(2)

来源:互联网 发布:淘宝网充值中心 编辑:程序博客网 时间:2024/06/05 11:24

NVM概述

新型非易失性存储介质,诸如闪存(flash) 、相变内存(phase-change memory, PCM) 、可变电阻式内存(ReRAM)等,可同时提供传统硬盘等外部存储器的数据持久化能力和接近动态随机访问内存(DRAM)等内部存储器的存取性能。非易失性内存介质及其软硬件系统共同构成持久性内存(persistent memory)系统, 可以融合传统易失性内部存储和非易失性外部存储的优良特性,提升上层应用软件和系统整体的性能。

持久性内存系统使得内存数据在系统发生故障时依然得以保留。该特性在减少传统持久化机制带来的性能损耗方面作用显著,但于此同时,也使得发生系统故障时的数据一致性(crash consistency)问题尤为突出。

Crash Consistency 与 Reordering Consistency

持久内存(PM/NVM)的一致性问题可以归结为两种:数据的部分写(partial write)与乱序写(reordering write)。

部分写问题是因为一个需要原子操作的数据写流程因系统故障发生而只写了一部分内容的一致性问题。

乱序写是CPU和内存的固有属性,对于DRAM来说不存在一致性问题。因为一旦掉电或系统故障,DRAM中的数据会全部丢失,没有与原来的数据一不一致这样的说法。但是由于NVM的非易失特性,重启系统程序后数据仍然在内存中,乱序写将可能会导致程序发生执行上的逻辑混乱。
举个简单的例子:

boolean flag = falseint a = 10;int b = 100;int *p = &b;*p = a * b;flag = true;if (flag == true) {    printf(" Multiplication is over!");    operate(*p); // operate is a series of operations based on value of p}

这一个样例执行了一个整型数据的乘法操作,该操作完成后,在实行一系列基于该结果的操作。如果cache到memory的数据传输不乱序,那么值得传递顺序依次为

a
b
p
b
flag
p

在以上任何一个传值过程中发生意外,程序重启后检查数据结果就可以继续运行无误(假定没有部分写问题)。然而如果发生数据乱序,那么写入内存的值结果可能如下:

a
b
p
flag
——————
b
p

如果不发生故障,那么程序也不会有任何问题,因为只有这些数据都被输出时才会执行if语句块内的内容。然而一旦故障发生在flag与b的传值结果之间,程序重新运行后flag已经为true,但b的结果仍是100而不是乘法操作后的1000。由于flagtrue,if语句块的内容可以继续执行,后续的过程因基于错误的b值,将会取得错误的结果,也就致使了不一致的发生。

NVM Consistency相关工作

而为保证故障时的数据一致性,往往需要对上层应用程序访问内存的接口加以限制。因此,数据一致性 机制及其应用程序接口方式在持久性内存系统性能、易用性及两者间的平衡等方面扮演着非常重要的角色。

关于NVM数据一致性的工作,我想重点介绍两个:

1.Mnemosyne: 这是2011年ASPLOS的一个工作,主要描述了两件事:如何管理非易失内存以及如何维护内存数据一致性。这里我们重点谈谈它的数据一致性保证工作。Mnemosyne支持四种类型的数据更新一致性:

  • 单变量更新 (适合flag数据或指针)
  • 只加内容更新 (适合log或文件内容追加)
  • 影子分页更新 (适合位图或树结构)
  • 原地更新 (适合任意数据类型)

Mneymosyne 利用基于硬件的原语操作(如mfence, mb, write-through)支持单变量更新。但涉及到原地更新技术的实现时,Mnemosyne做了比较复杂的实现,即通过修改内存控制器,实现了一个具有持久语义转换功能的编译器。这种方法使得用户可以通过在持久数据结构代码前加上持久化声明(如 ATOMIC)来实现数据持久化及维护一致性(通过事务内存机制记录log等)。

2.Heapo: 这是2013年的一个工作,部分重要思想直接继承自Mnemosyne 但有两点重要的区别:第一是它拥有自己管理的堆空间,是一个预先分配的大内存块,当用户调用Heapo的接口时就通过获取或映射到这些内存块上持久化数据;第二是Heapo可以使用不连续分配的虚拟地址空间。但直观上感觉不连续的虚拟地址空间会造成访问一整段数据结构时的不方便,不过由于Mnemosyne和Heapo采用的都是静态地址映射,所以每次系统重启程序重新运行后,物理地址和虚拟地址对是固定不变的 (这与Linux原来的内存映射机制不同)。Heapo的持久化方案相对来说更加简单,也是我们Daisy中借鉴采用的方案:利用undo日志和数据库系统中的事务机制,将对一个数据结构的操作约束为一个事务操作,仅当操作完成时事务才会提交(END标记),而事务中断时通过日志记录的log records使用undo操作来恢复相应地址空间的旧值。然而,Heapo的做法有一个限制,仅仅它所维的几种数据结构(链表,哈希表,B树)可以保证数据一致性,而其他的数据结构,比如红黑树,B+树,用户自定义数据结构及相关操作,则无法保证数据的一致性。

Daisy系统概述

Daisy(https://github.com/DDST-NVM/Daisy)是我们开发的一个轻量级持久内存管理系统,为用户提供方便的调用持久内存的接口。我们同样做到了对持久化内存的管理和一致性保证。我们与Mnemosyne和Heapo工作的主要区别是我们采取动态地址映射的方式因而不需要对原有的操作系统做更改,更加适于用户部署和操作。

如何使用

首先,请确保你为Linux系统分配的内存大于6GB (使用虚拟机尤其要注意这一点)。

git clone git@github.com:DDST-NVM/Daisy.git
cd Daisy/linux-3.12.49

sudo make mrproper
sudo make localmodconfig
sudo make
sudo make modules_install
sudo make install
sudo reboot -n

开机按住F12选择内核:linux-3.12.49
如不能正常开机(发生花屏现象),请重启并在grub界面按住“e”编辑 “quiet splash”, 若是Nrvdia显卡,在其后面添加“nomodeset”。

cd Daisy/pcmapi
./create_so.sh (生成持久内存接口库)
make
./ptest (请阅读test.c获取运行参数相关内容)

Daisy中的一致性问题

接口一致性

Undo Log

红黑树操作

更好的一致性保证方案?

组会上和老师汇报了近年来比较主流的一致性保证方案。但总体来说面临的一个窘境就是:对用户容易的方案(不需要修改代码即可保证数据一致性)多采用修改硬件(内存控制器)的方案解决;对用户复杂的方案(需要用户为数据结构编写一致性维护的代码,设计者仅提供持久化接口)则不太友善,且可移植性较差。

老师给我的建议是:不采用修改硬件的思路,构思出一种软件透明的方法来维护数据一致性。把任意数据结构和操作做一个抽象,保证这些抽象的数据及数据操作可以以原子性的方式实现在我们的系统上。如此一来,可以有一个粗粒度的持久化模型,再慢慢斟酌修改至一个比较合适可应用的状态。

我还需要再好好思考下,感觉懂得还是不多,所以才捉襟见肘吧。

2 0
原创粉丝点击