持久内存(PMem)科普
你说不定在不同的渠道已经听说过一些类似的让人一头雾水的技术名词,比如 非易失性存储,持久内存,傲腾持久内存,甚至英文的名词 Optane SSD, Optane persistent memory, PMem, DCPMM, AEP 等等…… 这些名词到底是什么?有什么联系?有什么用处?本文从科普的角度,帮你回答这些问题。希望你看了本文以后,不管你是程序员还是相关行业从业者,至少都能明白什么是持久内存,它到底能发挥什么样的作用。
持久内存到底是什么?
首先回答一下混乱的命名问题,我们暂时不纠结于这些名字之间的演化关系了,简单来说可以认为大部分都是指的同一个东西(当然不是严格正确)。目前Intel中文官方命名为“英特尔傲腾持久内存”,简称为“持久内存”。英文官方名为 Intel Optane Persistent Memory,简称为 PMem。因此在本篇文章中,统一使用“持久内存”或者“PMem”进行指代。
那么正式开始……说到底,持久内存其实是一种新型的内存条,我们可以先来看一下,它长这个样子,和普通内存条其实没啥特别大差异,而且它就是插在服务器的内存插槽里的。
所以简单来说,你可以直接从京东(https://item.jd.com/24641671886.html)上面买来,然后插到你的服务器上的内存插槽上,你就可以使用持久内存啦。当然,持久内存对于硬件是有一定的要求的,AMD的CPU就不用想了,持久内存属于 Intel 的独家法宝,自然不会留给竞争对手做支持。具体CPU的支持型号可以查看:https://discuss.memark.io/t/topic/22/2 当然如果想要发挥持久内存的最大优势,其在硬件配置插法上是有一定的讲究的,后面将会具体展开。
然后我们研究下持久内存在整个计算机体系架构中的位置。学过计算机的同学,一定对计算机的存储金字塔的架构非常熟悉,那么如果我们把持久内存也放到这个金字塔里,会是在什么位置呢?我们具体来看一下。如下图所示的存储金字塔中,我们可以看到持久内存处于外存(HDD或者SSD)以及内存DRAM之间,其不论在容量、性能、价格上都是处于两者的中间位置。除此以外,在功能上,它完全就是个DRAM和外存的混血儿(所以为什么在图上PMEM标记为一半是海水,一般是火焰)。也就是说,它即可以当做内存使用,也可以当做持久化外存设备使用,当然也可以两者兼顾,完全取决于你如何使用持久内存。
如果你还是不太能理解我描述的是什么,那么最直接的,告诉你持久内存三个最重要的特征:大, 快,持久性:
大:目前持久内存单条内存容量最大可以达到 512 GB,而目前服务器单条内存一般最多到 32/64 GB。也就是说,单台服务器使用持久内存可以轻松到达 TB 级别的内存容量。另一方面,单位价格来说,持久内存为普通内存的一半左右。
快:既然也号称为内存,那必然不能慢。可以看到,持久内存相比较于普通 SSD 有1-2个数量级的延迟性能优势,相比较于硬盘优势更加巨大。当然对比与DRAM,其会有一定的性能差距。但是实际使用中由于性能瓶颈不一定在内存上,所以一般不会有特别明显的差距(一般性能衰退在一倍以内)。
持久性:通俗来说,就是持久内存有跟硬盘一样的特性,断电以后重启,内存中的数据依然存在。此项特性可以说是秒杀内存,内存中的数据我们都知道断电或者程序以外退出以后就不复存在。此项特性使得持久内存即可以当做一个高速持久化设备使用,也可以满足内存应用某些场景下的快速恢复的需求。
如下表格总结了对于数据中心单台服务器上的典型配置,以及相应的大致的性能数字作为参考。
带宽 延迟 服务器典型内存容量 持久化?
硬盘 100 MB/sec 10 ms > 10 TB 是
硬盘(RAID-5) 400 MB/sec 10 ms > 10 TB 是
SATA SSD 500 MB/sec 200 us 10 TB 是
NVMe SSD 2.5 GB/sec 100 us 10 TB 是
PMem 50 GB/sec 1 us 3 TB 是
DDR4 100 GB/sec 100 ns 512 GB 否
常见内存和持久化设备在单台服务器上的大致性能表现
持久内存主要优势场景是什么?
说完了持久内存的特性,大家一定也能想象出它在某些应用场景下具有得天独厚的优势。具体来说,持久内存在实际落地中可能有以下几种玩法。以下从几个具体场景举例出发,并且辩证的给出使用持久内存带来的优势,以及可能引入的问题。
场景1:大内存低成本解决方案
如果你的应用内存消耗量是关键,是整个系统的资源瓶颈,那么使用持久内存将会是你降低成本的最佳解决方案。你的系统一般在两种情况下对于大内存有特别的需求
基于内存性能的考量,你必须使用基于内存的解决方案,而不可能使用基于磁盘的方案,比如内存数据库(Redis, MemSQL)。
虽然你的应用可以接受基于磁盘而带来的性能损耗,但是显然如果内存扩大,你的应用可以跑得更快更加节省时间,比如基于 Spark 搭建的应用。
此种场景下,你可以考虑使用持久内存来提供一个大内存低成本的解决方案。
优势:持久内存在单位价格上约为普通内存的一半,并且可以在单台机器上轻松达到 1.5 TB,甚至 3 TB 的内存大小。因此比如你目标需要 20 TB 的总内存容量,持久内存可能只需要10台机器即可满足,但是基于DDR内存的集群可能需要40台甚至更多。考虑机器投入以及运营上带来的成本,持久内存所带来的低成本解决方案的优势是显而易见的。
可能的问题:当然引入持久内存,相比较于内存可能会带来一定的性能衰退,衰退的原因可能是持久内存本身所引起的,也可能是由于机器台数减少,其他硬件资源(比如CPU核数或者网络带宽)减少所引起的。所以实际项目落地中,作为决策者,一定需要进行谨慎评估,来量化持久内存带来的利害关系。
场景2:高性能持久化需求的应用
持久内存作为一个内存和外存的混合体,其高速持久化的特性在某些磁盘 IO 作为性能瓶颈的场景下是一个破局的解法。虽然 SSD 一定程度上也可以缓解磁盘 IO 性能瓶颈,但是相比较于 PMem 这种可以实现两个数量级的吞吐和延迟改进的持久化设备来说,PMem 无疑是具有革命性的意义的。以下抛砖引玉举几个磁盘IO作为性能瓶颈的场景。
消息队列:大家熟悉的开源消息队列 Kafka,由于其消息持久化逻辑的存在,其吞吐最终会卡在硬盘 IO 上。目前的解法是不断堆机器来扩展整个 Kafka 集群的吞吐。
搜索系统:类似于 Kafka,流行的开源搜索系统 Elasticsearch,也将部分的数据结构存放在磁盘上。那么最终影响整体延迟和吞吐的将会是磁盘 IO 的性能。
数据库或者KV存储引擎:比如 MySQL 或者 RocksDB,都具有重要的面向外存的数据持久化逻辑。
分布式文件系统:在人工智能场景中,常常会有大量的小文件存在。比如在 Ceph 的文件系统中,在 metadata server 上对大量小文件的管理常常由于大量随机读写的存在而产生性能问题。
优势:显然,对于有高速持久化读写需求的场景,持久内存引入直接有了数量级的性能提升。在吞吐方面,由于单机吞吐提升,因此总的机器数量规模可以大量减少,在延迟方面则是提供了另一给维度的优势。具体性能比对可以参照上一节末尾给出的性能比对表格。
可能的问题:PMem 作为纯粹的持久化设备可能是把双刃剑,最主要的问题是其容量相比较于传统硬盘来说还是偏小,同时单位成本也高。因此对于某些场景下如果除了对于性能,对于容量也有较高的要求,那么使用 PMem 带来性能的提升,但是也可能会造成成本的上升。
延伸阅读:基于持久内存的 Kafka 改造方案
场景3:内存数据持久性的应用
这种场景下,本质上还是把 PMem 当做一个内存来使用,和上一个高性能持久化的场景有所相似有所区别。上一个场景主要是针对本来软件架构设计就有持久化逻辑(比如文件系统本来就需要存在硬盘上),然后我们把持久化逻辑搬移到PMem上就可以。其本身可能并不涉及到复杂的数据结构的修改,因为其本来的设计就已经带有了持久化逻辑。但是在场景 3 这种内存数据持久化场景中,软件本身的内存数据结构的设计是没有考虑到持久化逻辑的。因此你需要针对内存中的数据结构重新设计持久化数据结构和逻辑。这一类应用对开发的要求是最高的,同时也是最能完全发挥 PMem 的特点。
此种场景往往是本来就是基于纯内存的应用,但是希望增加数据持久的特性,最常见的需求是因为要快速数据恢复。此种需求一般来自线上服务系统(比如数据库 Redis,或者人工智能场景下的参数服务器、特征工程数据库等),线上服务一旦节点离线,都会造成服务质量的影响。由于系统是基于内存数据结构,离线以后的数据恢复往往需要小时级别的时间来重新抓取数据,并且重新构建内存中的数据结构。如果有了持久内存,此类服务不仅能够通过大内存降低成本,而且可以增加快速恢复功能,保证线上服务质量。
优势:如上所述,此种模式下,可以把持久内存的优势充分发挥出来。首先大内存带来硬件成本的下降,其次,通过持久性,赋予了本来的内存应用的新的持久化特性,可以支持数据快速回复,保证线上服务质量。
可能的问题:此种应用唯一的问题可能是带来比较多的额外的开发工作量。一般的内存数据结构都没有持久化逻辑,一般要求程序员通过 PMDK 重新设计持久化数据结构和逻辑,实现期望中的内存数据持久化。
延伸阅读
- 基于持久内存的实时特征工程数据库
- 基于持久内存的参数服务器
持久内存使用模式?
正是因为持久内存具有传统内存的特性,又兼具有外存的持久化特性,造就了其特殊的双模式使用方式。注意,两种模式不能混合使用,并且模式之前切换具有一定成本,无法做到程序运行时动态切换。
内存模式(Memory Mode)
顾名思义,就是把持久内存直接当做内存使用,不利用其非易失特性。这是一种最快速、低成本扩展内存容量的方式,对于程序完全透明。具体来说,操作系统将会直接看到持久内存的容量,而原来的DRAM将会被隐藏掉(实际上作为了持久内存的一层cache,其cache机制由CPU直接掌控)。程序无需改动任何代码,可以直接利用持久内存的大内存优势来运行内存消耗大的应用。
内存模式使用简单,但是也带来了一些问题:
可能的性能问题。由于DRAM被当做了PMem的一层cache,并且被CPU自动管理,但是PMem其在性能参数上是略低于DRAM的,所以在某些对于cache不友好的情况下,可能会带来性能较大的衰减。
无法使用持久化特性。 内存模式丢失了内存数据持久化的特性,无法用作对数据持久化有要求的场景。
App Direct 模式(AD Mode)
AD Mode 实际上是把内存层级完全暴露给了应用。程序员需要自己控制将数据存放在DRAM或者持久内存,自己掌握是否要进行内存数据的持久化操作。因此,其优势正好是克服了内存模式的两个问题:
存储层级对程序员可见,因此应用可以根据自己的特点进行存储性能优化,比如冷热数据的分级存储,以及使用缓存敏感的数据结构(cache conscious)
数据持久性在AD Mode下可用,程序员可以选择是否将数据在持久内存上做持久化操作,从而达到利用高速持久化能力,或者给程序带来快速恢复的能力
但是,AD Mode 带来的问题在于研发成本的提升。由于持久化编程模型的引入,原来基于内存的程序可能需要重新架构才能在多级存储的内存架构上发挥优势。
如何做持久内存的开发?
首先必须弄明白,如果memory mode这种低成本扩展内存容量的方式可以满足你的业务需求,那么你根本不需要开发成本。但是如果不能满足你的需求,存在以下几种问题,那么你可能得动脑子想想需要如何对现有场景进行改造。
内存模式性能衰退过于明显,希望使用大容量内存的同时,保持和DRAM接近的性能
想利用持久内存来替代(或者一部分替代)传统外存设备,利用其高速持久化特性
希望对内存数据做持久化,提供离线以后的快速恢复功能
持久内存的开发会是一个非常大的topic,而且根据你想要达到的目的不同,思路会完全不一样,我们这里不做展开。我们建议你移步我们另外一篇文章:https://memark.io/index.php/2021/04/09/pmem_intro/
同时,如果在学习开发过程中有任何的疑问,不要忘记我们的技术论坛 https://discuss.memark.io/
持久内存的参考案例和项目
最后,作为一个新兴的技术,持久内存从2019年正式发布以后,正处在生根发芽的阶段,工业界已经有不少的成功案例可供参考,比如
快手推荐系统及 Redis 升级存储借傲腾™ 补上 DRAM 短板
快手联手英特尔提升 KGNN 平台大规模实时动态图训练效率
百度 Feed 流服务借助傲腾™ 技术重构内存数据库
英特尔、第四范式联合研究成果入选国际顶会 VLDB 傲腾™ 持久内存加持 优化万亿维特征在线预估系统
第四范式推出业界首个基于持久内存、支持毫秒级恢复的万亿维线上预估系统
持久内存相关的最重要的开源项目肯定是 Intel 自己家的 Persistent Memory Programming ,其中比较重要的几个repo包括:
pmdk: https://github.com/pmem/pmdk 最底层的基础性编程库,覆盖最全的功能,但也是最繁琐的操作方式
libpmemobj-cpp: https://github.com/pmem/libpmemobj-cpp 以C++绑定的PMDK里面最重要的一些概念和基础数据结构,作为入门开发者的首选
pmemkv: https://github.com/pmem/pmemkv 最为基础的持久内存应用 KV Store,兼具有高性能内存查询和数据持久化能力
此外,也请关注我们 MemArk 社区主导开发的若干项目
Pafka: https://github.com/4paradigm/pafka ,Kafka 基于持久内存架构优化的高性能版本
PmemStore: https://github.com/4paradigm/pmemstore , pmemkv的改进版本,引入针对人工智能工作负载优化的数据结构,高性能处理时间窗口相关查询