当前位置: 首页 > 工具软件 > NVM-Direct > 使用案例 >

40 Redis 的下一步发展:基于NVM内存的实践

昝阳嘉
2023-12-01


前言

近年新型非易失存储(Non-Volatile Memory,NVM)器件发展得非常快。NVM 器件具有容量大、性能快、能持久化保存数据的特性,这些刚好就是 Redis 追求的目标。 同时 NVM 器件像 DRAM 一样,可以让软件以字节粒度进行寻址访问,所以在实际应用中 NVM 可以作为内存来使用,称为 NVM 内存

Redis 作为内存键值数据库,如果能和 NVM 内存结合起来使用,就可以充分享受到这些特性。Redis 发展的下一步可以基于 NVM 内存来实现大容量实例,或者是实现快速持久化数据和恢复。

一、NVM 内存的特性与使用模式

Redis 是基于 DRAM 内存的键值数据库,而跟传统的 DRAM 内存相比,NVM 有三个显著的特点:

  1. NVM 内存最大的优势是可以直接持久化保存数据。数据保存在 NVM 内存上后,即使发生了宕机或是掉电,数据仍然存在 NVM 内存上。但如果数据是保存在 DRAM 上,掉电后数据就会丢失。
  2. NVM 内存的访问速度接近 DRAM 的速度。实际测试 NVM 内存的访问速度, 读延迟大约是 200 - 300ns,而写延迟大约是 100ns。在读写带宽方面,单根 NVM 内存条的写带宽大约是 1 - 2GB/s,而读带宽约是 5~6GB/s。当软件系统把数据保存在 NVM 内存上时,系统仍然可以快速地存取数据。
  3. NVM 内存的容量很大。因为 NVM 器件的密度大,单个 NVM 的存储单元可以保存更多数据。例如,单根 NVM 内存条就能达到 128GB 的容量,最大可以达到 512GB,而单根 DRAM 内存条通常是 16GB 或 32GB。很轻松地用 NVM 内存构建 TB 级别的内存。

NVM 内存的特点可以用三句话概括:

  1. 能持久化保存数据;
  2. 读写速度和 DRAM 接近;
  3. 容量大。

现在业界已经有了实际的 NVM 内存产品是 Intel 在 2019 年 4 月份时推出的 Optane AEP 内存条(简称 AEP 内存)。在应用 AEP 内存时,需要注意 AEP 内存给软件提供了两种使用模式,分别对应着使用了 NVM 的容量大和持久化保存数据两个特性:

  1. Memory 模式把 NVM 内存作为大容量内存来使用,只使用 NVM 容量大和性能高的特性,没有启用数据持久化的功能。例如,在一台服务器上安装 6 根 NVM 内存条,每根 512GB,在单台服务器上获得 3TB 的内存容量了。
    在 Memory 模式下,服务器上仍然需要配置 DRAM 内存,但是 DRAM 内存是被 CPU 用作 AEP 内存的缓存,DRAM 的空间对应用软件不可见。换句话说,软件系统能使用到的内存空间,就是 AEP 内存条的空间容量。

  2. App Direct 模式启用了 NVM 持久化数据的功能。应用软件把数据写到 AEP 内存上时,数据就直接持久化保存下来了。也叫做持久化内存(Persistent Memory,PM)

二、基于 NVM 内存的 Redis 实践

当 AEP 内存使用 Memory 模式时,应用软件就可以利用它的大容量特性来保存大量数据,Redis 也就可以给上层业务应用提供大容量的实例了。而且在 Memory 模式下, Redis 可以像在 DRAM 内存上运行一样,直接在 AEP 内存上运行,不用修改代码。

不过需要注意:在 Memory 模式下,AEP 内存的访问延迟会比 DRAM 高一 点。NVM 的读延迟大约是 200~300ns,而写延迟大约是 100ns。所以在 Memory 模式下运行 Redis 实例,实例读性能会有所降低,就需要在保存大量数据和读性能较慢两者之间做个取舍。

当使用 App Direct 模式,把 AEP 内存用作 PM 时,Redis 利用 PM 快速持久化数据的特性,和 Redis 的数据可靠性保证需求和现有机制有关:

为了保证数据可靠性,Redis 设计了 RDB 和 AOF 两种机制,把数据持久化保存到硬盘上。

但是无论 RDB 还是 AOF,都需要把数据或命令操作以文件的形式写到硬盘上。

对于 RDB 来说,虽然 Redis 实例可以通过子进程生成 RDB 文件,但是实例主线程 fork 子进程时,仍然会阻塞主线程。而且 RDB 文件的生成需要经过文件系统,文件本身会有一定的操作开销。

对于 AOF 日志来说,虽然 Redis 提供了 always、everysec 和 no 三个选项,其中 always 选项以 fsync 的方式落盘保存数据,虽然保证了数据的可靠性,但是面临性能损失的风险。everysec 选项避免了每个操作都要实时落盘,改为后台每秒定期落盘。此时 Redis 的写性能得到了改善,但是应用会面临秒级数据丢失的风险。

此外使用 RDB 文件或 AOF 文件对 Redis 进行恢复时,需要把 RDB 文件加载到内存中,或者是回放 AOF 中的日志操作。这个恢复过程的效率受到 RDB 文件大小和 AOF 文件中的日志操作多少的影响。

所以不要让单个 Redis 实例过大,否则会导致 RDB 文件过大。在主从集群应用中,过大的 RDB 文件就会导致低效的主从同步。

Redis 在涉及持久化操作时的问题:

  1. RDB 文件创建时的 fork 操作会阻塞主线程;
  2. AOF 文件记录日志时,需要在数据可靠性和写性能之间取得平衡;
  3. 使用 RDB 或 AOF 恢复数据时,恢复效率受 RDB 和 AOF 大小的限制。

但是,如果使用持久化内存,就可以充分利用 PM 快速持久化的特点,来避免 RDB 和 AOF 的操作。因为 PM 支持内存访问,而 Redis 的操作都是内存操作,就可以把 Redis 直接运行在 PM 上。同时数据本身就可以在 PM 上持久化保存了,就不再需要额外的 RDB 或 AOF 日志机制来保证数据可靠性了。

PM 的使用方法:

当服务器中部署了 PM 后,可以在操作系统的 /dev 目录下看到一个 PM 设备,如下所示:

/dev/pmem0

然后需要使用 ext4-dax 文件系统来格式化这个设备:

mkfs.ext4 /dev/pmem0

接着把这个格式化好的设备,挂载到服务器上的一个目录下:

mount -o dax /dev/pmem0 /mnt/pmem0

此时就可以在这个目录下创建文件了。创建好了以后,再把这些文件通过内存映射 (mmap)的方式映射到 Redis 的进程空间。这样就可以把 Redis 接收到的数据直接保存到映射的内存空间上了,而这块内存空间是由 PM 提供的。所以数据写入这块空间时,就可以直接被持久化保存了。

如果要修改或删除数据,PM 本身也支持以字节粒度进行数据访问,所以 Redis 可以直接在 PM 上修改或删除数据。

如果发生了实例故障,Redis 宕机了,因为数据本身已经持久化保存在 PM 上了,可以直接使用 PM 上的数据进行实例恢复,而不用再像现在的 Redis 那样,通过加载 RDB 文件或是重放 AOF 日志操作来恢复了,可以实现快速的故障恢复。

当然,因为 PM 的读写速度比 DRAM 慢,如果使用 PM 来运行 Redis,需要评估 下 PM 提供的访问延迟和访问带宽,是否能满足业务层的需求。

评估 PM 带宽对 Redis 业务的支撑:

假设业务层需要支持 1 百万 QPS,平均每个请求的大小是 2KB,需要机器能支持 2GB/s 的带宽(1 百万请求操作每秒 * 2KB 每请求 = 2GB/s)。如果这些请求正好是写操作的话,单根 PM 的写带宽可能不太够用了。

这个时候可以在一台服务器上使用多根 PM 内存条,来支撑高带宽的需求。当然也可以使用切片集群,把数据分散保存到多个实例,分担访问压力。

总结

NVM 的三大特点:性能高、容量大、数据可以持久化保存。软件系统可以像访问传统 DRAM 内存一样,访问 NVM 内存。

目前 Intel 已经推出了 NVM 内存产品 Optane AEP。提供了两种使用模式,分别是 Memory 模式和 App Direct 模式。

在 Memory 模式时,Redis 可以利用 NVM 容量大的特点,实现大容量实例,保存更多数据。

在使用 App Direct 模式时,Redis 可以直接在持久化内存上进行数据读写,Redis 不用再使用 RDB 或 AOF 文件了,数据在机器掉电后也不会丢失。而且,实例可以直接使用持久化内存上的数据进行恢复,恢复速度特别快。

NVM 内存是近年来存储设备领域中一个非常大的变化,它既能持久化保存数据,还能像内存一样快速访问,这必然会给当前基于 DRAM 和硬盘的系统软件优化带来新的机遇。

 类似资料: