• 存储架构颠覆者Optane持久性内存


    Intel中文官方命名为“英特尔傲腾持久内存”,简称为“持久内存”。英文官方名为 Intel Optane Persistent Memory,简称为 PMem,物理封装为DIMM,直接插在内存插槽上,也可以插在PCIe插槽上。他的特性就是大, 快,持久性。

    Intel称Optane Memory为Apache Pass(AEP),为高性能和灵活性而设计的革命性的SCM,称Optane NVMe SSD为Clodstream。

    一、基础信息

    如下图所示的存储金字塔中,我们可以看到持久内存处于外存(HDD或者SSD)以及内存DRAM之间,其不论在容量、性能、价格上都是处于两者的中间位置。除此以外,在功能上,它完全就是个DRAM和外存的混合。也就是说,它即可以当做内存使用,也可以当做持久化外存设备使用,当然也可以两者兼顾,完全取决于你如何使用持久内存。

     CPU通过load/store指令访问存储设备,即数据直接以cache line(64 byte)的粒度从寄存器中copy到存储设备中,或者从存储设备中copy到寄存器。而PMEM以下都是可持久化的存储设备,通过向I/O控制器发送命令,以block的粒度将数据换入换出到DRAM中,然后才能直接被CPU访问。

    DRAM的容量没办法做得很大,服务器上主流的DRAM一般为16G或32G,容量再大功耗相应也会增加。而且DRAM的价格比较高,数据不能持久化。

    对于SSD等一些块设备来说,确实能够满足大容量持久化的要求,但是访问延迟却是DRAM的1000多倍,同时块设备存在随机访问能力比较差的问题。虽然近些年来出现了以rocksdb/leveldb为代表的LSM-Tree结构的存储系统从一定程度上解决了块设备低效的写问题,但同时又引入了一个比较严重的写放大问题。

    SSD与DRAM的访问延迟差异导致在他们之间形成了一条巨大的鸿沟,持久化内存的出现正好填补上了他们之间的差异。

    IMC(integrated memory controller)与AEP之间以cache line大小的粒度传输数据,但是AEP的ECC(Error correction code) size为256字节,即AEP内部的controller与介质之间是以256字节(4个cache line)为单位进行读写。同时AEP的读写不对称,读性能明显优于写性能,所以应该避免频率的写入小对象。

    AEP有两种工作模式:Memory Mode和App Direct Mode,如果细分就还有Storage Over App Direct

     Memory Mode

    根据AEP在存储层次结构中所处的位置,自然想到的是将DRAM作为AEP的缓存,AEP中的热数据缓存在DRAM中,这也符合计算机存储系统一惯的设计思想。在这种模式下AEP和DRAM共同组成了一块对上层透明且容量更大的易失性内存,这时系统的总容量等于AEP的容量,应用无需做任何额外的修改即可使用。DRAM到AEP的缓存算法由IMC(集成在CPU里的memory controller)硬件管理。

    AppDirect Mode

    应用可以不经过DRAM而直接访问AEP,用由应用自己管理,这种使用方式叫做AppDirect Mode。

    为了简化持久化内存在AppDirect下的使用,Intel开发了PMDK(Persistent Memory Development Kit)。我们可以直接在PMDK的基础上去开发自己的应用,但是这些通用的库也并不一定适合所有场景。

    下面这几个库用的比较多一些:
    1. libpmem: 用来将数据持久化到介质上,以及提供一些优化的内存操作(memcpy, memset等)函数。
    2. libpmemlog: 基于这个库可以用来写顺序追加的log等。
    3. ibpmemobj: 这个库实现了一套事务机制,用来保证数据的一致性问题

    二、编程模型

    这个针对PMEM的编程模型叫做SNIA(storage network industry association) 细节可以参考 SNIA,介绍了用户如何来通过标准接口访问PMEM低层。

     

        Persistent Memory 部分中:有两种访问NVDIMMs (底层PMEM存储)的方式,第一种是pmdk,以pmem_mmap方式访问,第二种是通过pmem aware-fs来访问, 这个pmem aware-fs是pmem设备支持的一种适配文件系统,可以提供标准用户访问的API(read,write,pread,pwrite…)。
        Block中 操作系统抽象出 NVDIMM driver可以在其上格式化标准文件系统(xfs/ext4),对外提供文件系统API;同时也能够对外提供标准设备API 来直接访问 driver。
        第三种就是 NVME driver提供了UI ,可以通过UI直接访问NVMDIMM。

    PMDK

    PMDK 则是官方为 PMEM的管理员和应用开发者抽象出来的用户态接口,能够极大得简化用户操作pmem的成本。
    接口架构

    persistent memory development kit 接口 提供了大量的编程接口,足以应对用户的各种复杂操作的需求。

    对外接口 以及 不同的库之间关系如下:

    接口概览

        libpmem 提供最底层的库给应用,保证数据能够持久化。只是不保证原子性和一致性(没有事务),如果用户直接用这一个库,则需要自己保证这一些特性。

        librpmem类似libpmem 提供的持久化能力 以及一些问题,只是这个库支持通过RDMA访问远端的PMEM 设备。

        libpmemlog 提供能够持久化的log 库

        libpmemobj 用户主要是使用的库,提供了持久化、事务、内存管理、锁、基本数据结构(链表。。),保证了原子性和一致性。

        libpmemblk 提供持久化的块存储,保证了块数据的原子更新和下电不丢失。

        libmemkind 用作pmem的内存模式,可以通过malloc/free申请释放空间,就像使用DDR一样。

    pmdk 安装

    下面主要介绍的是linux 系统的安装,关于windows 的安装,可以参考https://github.com/pmem/pmdk

        依赖安装:

    yum install autoconf pkg-config ndctl-devel daxctl-devel pandoc -y

        最新版本的pmdk 会依赖更高版本的ndctl,而这个较高版本的ndctl无法通过yum直接安装,只能通过源码编译安装。
        这个过程中遇到的问题挺多的,当然看个人系统,如果系统库安装的比较全,可能也一次通过,简单记录一下。

    1. git clone https://github.com/pmem/ndctl.git
    2. cd ndctl
    3. git checkout v71 # 当前的最新版本
    4. ./autogen.sh
    5. Activated pre-commit hook.
    6. GIT_VERSION = 71
    7. sh: aclocal: command not found
    8. autoreconf: aclocal failed with exit status: 127 # 执行失败
    9. ----------------------------------------------------
    10. # 解决
    11. sudo yum install automake libtool -y
    12. autoreconf -ivf
    13. # 执行成功
    14. $ ./autogen.sh
    15. ----------------------------------------------------------------
    16. Initialized build system. For a common configuration please run:
    17. ----------------------------------------------------------------
    18. ./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
    19. # 执行./configure
    20. ./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
    21. ...
    22. checking for a sed that does not truncate output... (cached) /usr/bin/sed
    23. checking for asciidoctor... missing
    24. configure: error: asciidoctor needed to build documentation # 执行失败
    25. ----------------------------------------------------
    26. # 解决
    27. sudo yum install asciidoctor -y
    28. # 重新执行 ./configure
    29. ./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
    30. ...
    31. checking for KMOD... no
    32. configure: error: Package requirements (libkmod) were not met:
    33. No package 'libkmod' found
    34. Consider adjusting the PKG_CONFIG_PATH environment variable if you
    35. installed software in a non-standard prefix # 执行失败
    36. ----------------------------------------------------
    37. #解决
    38. sudo yum install kmod kmod-devel -y
    39. # 再次重新执行 ./configure
    40. ./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
    41. ...
    42. configure: error: Package requirements (uuid) were not met:
    43. No package 'uuid' found #执行失败
    44. ----------------------------------------------------
    45. #解决
    46. sudo yum install libuuid-devel json-c-devel -y
    47. # 执行./configure 成功,生成 Makefile
    48. ./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
    49. # 安装ndctl
    50. make && sudo make install

        编译:

    1. # 获取代码
    2. git clone https://github.com/pmem/pmdk
    3. cd pmdk
    4. git checkout stable-1.10 # 这一步也可以跳过,直接编译master分支
    5. # 编译 ,建议以root用户来执行
    6. make EXTRA_CFLAGS="-Wno-error"
    7. make install prefix=/usr/local # 如果没有root用户,可以指定自己的安装prefix,默认是/usr/local

     

    三、PMEM性能

    官方性能 参考链接: https://www.intel.com/content/www/us/en/products/docs/memory-storage/optane-persistent-memory/optane-persistent-memory-200-series-brief.html

    其中 以128G容量为例:

        写入单元为256B时,能够提供292PB 的总写入寿命,6.8GB/s的读带宽,1.85GB/s的写带宽,依次读写延时基本都在百ns量级
        写入单元为64B时,寿命以及读写带宽都有下降。只能写入91PB的总数据量,读写带宽分别只有1.7Gb/s和0.45GB/s。因为PMEM的字节寻址的基本单元也是256B,也就是如果只写入64B,需要占用256B的存储空间,如果底层要写入的单元有数据,则需要先读取256B的数据单元,将64B的数据添加进去,再把256B的单元整体写入到PMEM中。这个过程会极大得降低读写性能,所以,针对PMEM的编程建议256B对齐,这样对pmem的性能更加友好。

  • 相关阅读:
    【鸿蒙开发】第十七章 Web组件(一)
    队列(JAVA)
    Java 集合的常用操作(ArrayList, LinkedList, HashSet, HashMap)
    [PAT练级笔记] 41 Basic Level 1041 考试座位号
    34、幂等性
    无损分区工具对电脑硬盘分区,介绍一款硬盘无损分区工具
    shiro面试题
    音视频学习 - Qt6.3.1版本下实现屏幕截图功能
    阶乘分解质因数
    设计师值得收藏的5个设计网站
  • 原文地址:https://blog.csdn.net/cyq6239075/article/details/126548989