北京哪个看白癜风的医院好 https://baike.baidu.com/item/%E5%8C%97%E4%BA%AC%E4%B8%AD%E7%A7%91%E7%99%BD%E7%99%9C%E9%A3%8E%E5%8C%BB%E9%99%A2/9728824?fr=aladdin作者张鹏义,腾讯云数据库高级工程师,曾参与华为Taurus分布式数据研发及腾讯CynosDBforPG研发工作,现从事腾讯云Redis数据库研发工作。
存储体系结构
回顾一下计算机的存储体系结构。正如下图所示,计算机存储设备根据访问速度及容量等形成了一个金字塔形的层次结构。在这个层次结构中,从上到下,设备的访问时延越来越大,容量也越来越大,而每字节的造价也越来越便宜。在这个层次结构中,每一层都被看作是其下一层次的缓存。
同时在这个层次结构中存在一个明显的分界线,如图中绿色的虚线。在分界线以上都是易失性的设备,掉电数据丢失,CPU通过load/sto指令访问存储设备,即数据直接以cacheline(64byte)的粒度从寄存器中copy到存储设备中,或者从存储设备中copy到寄存器。而分界线以下都是可持久化的存储设备,通过向I/O控制器发送命令,以block的粒度将数据换入换出到DRAM中,然后才能直接被CPU访问。
随着近互联网的发展,数据密集型应用已然成为主流,其主要特点表现为数据容量大,对数据分析的实时性及数据存储的高效性提出了更高的要求,以spark、dis为代表的基于内存的数据分析与存储系统广受欢迎。
但是DRAM的容量受限于晶体管-电容式(1T1C)单元的密度,以及难以扩展的动态刷新(fsh)操作,DRAM的容量没办法做得很大,服务器上主流的DRAM一般为16G或2G,容量再大功耗相应也会增加。而且DRAM的价格比较高,数据不能持久化。
对于SSD等一些块设备来说,确实能够满足大容量持久化的要求,但是访问延迟却是DRAM的多倍,同时块设备存在随机访问能力比较差的问题。虽然近些年来出现了以rocksdb/leveldb为代表的LSM-Te结构的存储系统从一定程度上解决了块设备低效的写问题,但同时又引入了一个比较严重的写放大问题。
SSD与DRAM的访问延迟差异导致在分界线处形成了一条巨大的鸿沟,持久化内存的出现正好给填补上了。
持久化
持久化内存在存储体系层次结构中的位置如下图所示,它位于DRAM与SSD之间,同时注意到它是横跨在分界线上的,它模糊了传统层次结构中内存与外存的边界,它既具有DRAM一样的数据访问方式,也具有SSD一样的持久化特性。所以可以把它当成内存或者持久化的存储使用。
InteloptaneDCpersistentmemory是Intel推出的基于DXpoint技术的持久化内存产品,其代号为ApacePass(AEP)。AEP的物理封装为DIMM,直接插在内存插槽上,单条AEP的容量目前已经达到了G,如上图所示,如果一半的插槽插上AEP,那么单个CPU内存容量很轻松的就可以扩展到TB以上。IMC(integratedmemorycontroller)与AEP之间以cacheline大小的粒度传输数据,但是AEP的ECC(Errorcorctioncode)size为字节,即AEP内部的controller与介质之间是以字节(4个cacheline)为单位进行读写。同时AEP的读写不对称,读性能明显优于写性能,所以应该避免频率的写入小对象。
AEP工作模式
AEP有两种工作模式:MemoryMode和AppDictMode,如果细分就还有StorageOverAppDict。
一、MemoryMode
根据AEP在存储层次结构中所处的位置,自然想到的是将DRAM作为AEP的缓存,AEP中的热数据缓存在DRAM中,这也符合计算机存储系统一惯的设计思想。在这种模式下AEP和DRAM共同组成了一块对上层透明且容量更大的易失性内存,这时系统的总容量等于AEP的容量,应用无需做任何额外的修改即可使用。DRAM到AEP的缓存算法由IMC(集成在CPU里的memorycontroller)硬件管理。
当前的缓存策略采用dict-mapped-cache算法实现,数据以cacheline的粒度换入换出,但是这种算法会把AEP中多块内存映射到DRAM中的同一个位置,以致于在某些场景下出现冲突不命中的情况可能比较严重。所以这么一个通用的算法并不能很好地将热数据从AEP中分离出来。
MemoryMode配置方法:
ipmctlcate-goalmemorymode=(ipmctl是Intel开发的一个管理持久化内存的工具)boot后fe-g就可以看到系统内存容量等于AEP的总容量。
二、AppDictMode
应用可以不经过DRAM而直接访问AEP,用由应用自己管理,这种使用方式叫做AppDictMode。那么在这种模式下应用怎么访问AEP?SNIA(StorageNetworkingIndustryAssociation)制定了一套编程模型,如下图所示,其中NVDIMM指非易失性内存模块,即AEP设备。
传统的文件系统都有一层pagecache,访问数据时先将数据copy到pagecache中,然后再copy到应用buffer中。对于低延迟及可按字节寻址的AEP来说,没这个必要。Pmem-AwaFileSystem指的是支持直接访问设备(DAX)的文件系统,DAX特性从IO路径上移除pagecache,同时允许mmap()直接建立到持久化内存的映射关系。目前ext4和xfs都已支持DAX特性。
AppDictMode配置方法:ipmctlcate-goalPersistentMemoryType=appdictboot(boot后就可以在/dev下看到pmem0,pmem1设备)ndctlcate-namespace-mfsdax-r0mkfs-text4/dev/pmem0mount-odax/dev/pmem0/mnt/pmem0(-odax开启DAX)
配置完成后就可以在/mnt/pmem0下创建、删除、读写文件了,但是一般不会直接这么使用。通常在/mtn/pmem0/上通过mmap建立memory-mapfile,一旦映射建立后,用户虚拟地址空间通过MMU就直接映射到AEP的物理空间中,应用无需陷入内核态即可高效地以字节寻址的方式访问AEP。再借助于libmemkind库,就可像使用DRAM一样来使用AEP。Libmemkind将cate/openfile,mmap进行了封闭,并提供类malloc/fe的接口在AEP上分配内存。所以应用需要显示通过类malloc/fe接口决定哪些数据直接写到AEP,对已经代码要做一定的修改。
要注意的是mmap必须是以shad的方式建立映射,如果是以private的方式映射,更新数据时并不会写到介质上,而是写到进程私有的空间中(pagecache中),然而这里AppDict模式下是没有pagecache的。这里引出了一个问题:如果进程在AEP中分配了一块内存,然后fork一个子进程,那么子进程也是能够看到父进程对这块内存的更新,因为两个父子进程的更新都会立即反映到同一块物理内存上。所以对于分配在AEP上的内存就没办法利用fork的copyonwrite机制来获取一致性的内存状态。(Redis正是利用fork的copyonwrite机制获取一对致性内存状态做备份操作)。
AppDict下即可以将AEP当作易失性的内存使用也可以当作持久化的内存使用。当作易失性内存使用时,仅仅是我们不