dot 速度的未来即将在您所在的城市举办的活动中到来。

加入我们参加 Redis 发布会

13 年后 - Redis 需要新的架构吗?

Redis 是一项基础技术,因此,我们偶尔会看到人们考虑其他架构。几年前,KeyDB 提出了这个问题,最近一个新项目 Dragonfly 声称是速度最快的 Redis 兼容内存数据存储。我们相信这些项目带来了许多值得讨论和争论的有趣技术和理念。在 Redis,我们喜欢这种挑战,因为它要求我们重申 Redis 最初设计时的架构原则(致敬 Salvatore Sanfilippo,也称为 antirez)。

虽然我们一直在寻找机会创新并提高 Redis 的性能和功能,但我们希望分享我们的观点,并对为什么 Redis 的架构仍然是内存中实时数据存储(缓存数据库 及其间的一切)的最佳选择进行一些反思。

因此,在接下来的部分中,我们将重点介绍我们对速度和架构差异的看法,这些看法与正在进行的比较相关。在这篇文章的最后,我们还提供了与 Dragonfly 项目相关的基准测试和性能比较的详细信息,我们将在下面讨论,并邀请您自行查看和复制这些详细信息。

速度

Dragonfly 基准测试 将独立的单进程 Redis 实例(只能利用单个核心)与多线程 Dragonfly 实例(可以利用 VM/服务器上所有可用的核心)进行比较。不幸的是,这种比较并不代表 Redis 在现实世界中的运行方式。作为技术构建者,我们努力了解我们的技术与其他技术的精确比较方式,因此我们做了我们认为是公平的比较,并将一个 40 分片的 Redis 7.0 集群(可以利用大部分实例核心)与 Dragonfly 进行了比较,使用一组性能测试,这些测试是在 Dragonfly 团队在其基准测试中使用的最大实例类型上进行的,AWS c6gn.16xlarge。在我们的试验中,我们看到 Redis 实现了比 Dragonfly 高 18% - 40% 的吞吐量,即使只利用了 64 个 vCore 中的 40 个。

架构差异

一些背景

我们相信这些多线程项目创建者做出的许多架构决策都受到他们在之前工作中遇到的痛点的影响。我们同意,在一个多核机器上运行单个 Redis 进程,有时有数十个核心和数百 GB 的内存,不会利用明显可用的资源。但这并不是 Redis 的设计使用方式;这只是许多 Redis 提供商选择运行其服务的方式。

Redis 通过运行多进程(使用 Redis 集群)进行水平扩展,即使是在单个云实例的上下文中也是如此。在 Redis(公司)中,我们进一步发展了这一概念,并构建了 Redis Enterprise,它提供了一个管理层,允许我们的用户大规模运行 Redis,并默认启用高可用性、即时故障转移、数据持久性和备份。

我们决定分享我们在幕后使用的一些原则,以帮助人们了解我们认为在生产环境中运行 Redis 的良好工程实践。

架构原则

每个 VM 运行多个 Redis 实例

在每个 VM 上运行多个 Redis 实例使我们能够

  1. 线性扩展,既可以垂直扩展,也可以水平扩展,使用完全无共享的架构。与仅垂直扩展的多线程架构相比,这将始终提供更大的灵活性。
  2. 提高复制速度,因为复制是在多个进程中并行完成的。
  3. 从 VM 故障中快速恢复,因为新 VM 的 Redis 实例将同时从多个外部 Redis 实例中获取数据。

将每个 Redis 进程限制为合理的大小

我们不允许单个 Redis 进程的大小超过 25 GB(运行 Redis on Flash 时为 50 GB)。这使我们能够

  • 在进行复制、快照和 Append Only File (AOF) 重写时,享受写时复制的优势,而无需为大型内存开销付出代价。而且,如果您没有这样做,您(或您的用户)将付出高昂的代价,如 这里 所示。
  • 轻松管理我们的集群,以快速的方式迁移分片、重新分片、扩展和重新平衡,因为每个 Redis 实例都保持较小。

水平扩展至关重要

能够使用水平扩展运行内存中数据存储非常重要。以下是一些原因:

  • 更好的弹性 - 在您的集群中使用的节点越多,您的集群就越健壮。例如,如果您在 3 节点集群上运行您的数据集,并且一个节点降级,那么 1/3 的集群将无法运行;但是,如果您在 9 节点集群上运行您的数据集,并且一个节点降级,那么只有 1/9 的集群无法运行。
  • 更易于扩展 - 将一个额外的节点添加到您的集群中并将您的数据集的一部分迁移到该节点中,比垂直扩展更容易,因为在垂直扩展中,您需要引入一个更大的节点并将整个数据集复制到该节点中(并考虑所有可能在这个可能很长的过程中发生的不利情况……)。
  • 逐步扩展更具成本效益 - 垂直扩展,尤其是在云中,非常昂贵。在许多情况下,您需要将实例大小翻倍,即使您只需要为您的数据集添加几个 GB。
  • 高吞吐量 - 在 Redis,我们看到许多客户在小型数据集上运行高吞吐量工作负载,这些工作负载具有非常高的网络带宽和/或高每秒数据包 (PPS) 需求。考虑一个 1 GB 数据集,其操作数/秒为 1M+。在单个节点 c6gn.16xlarge 集群(128 GB,64 个 CPU,100gbps,价格为 2.7684 美元/小时)上运行它是否比在 3 节点 c6gn.xlarge 集群(8 GB,4 个 CPU,高达 25Gbps,价格为 0.1786 美元/小时,每个)上运行更有意义,其成本不到 20%,并且更健壮?能够在保持成本效益和提高弹性的同时提高吞吐量似乎是一个简单的答案。
  • NUMA 的现实 - 垂直扩展还意味着运行一个带有多个核心和大型 DRAM 的双插槽服务器;这种 NUMA 架构非常适合像 Redis 这样的多处理架构,因为它更像是一个较小节点的网络。但是,NUMA 对多线程架构更具挑战性,根据我们对其他多线程项目的经验,NUMA 会将内存中数据存储的性能降低多达 80%。
  • 存储吞吐量限制 - 像 AWS EBS 这样的外部磁盘的扩展速度不如内存和 CPU 快。实际上,云服务提供商会根据使用的机器类型对存储吞吐量施加限制。因此,为了有效地扩展集群以避免已描述的问题并满足高数据持久性要求,唯一的方法是使用水平扩展,即通过添加更多节点和更多网络连接的磁盘。
  • 临时磁盘 - 临时磁盘是将 Redis 运行在 SSD 上(SSD 用作 DRAM 替代品,但不用作持久存储)并享受磁盘型数据库的成本,同时保持 Redis 速度的绝佳方式(查看我们使用 Redis on Flash 的方式)。同样,当临时磁盘达到其限制时,最好的方法,在许多情况下也是唯一的方法,是通过添加更多节点和更多临时磁盘来扩展您的集群。
  • 商品硬件 - 最后,我们许多本地客户都运行在本地数据中心、私有云,甚至小型边缘数据中心;在这些环境中,可能很难找到内存超过 64 GB 且 CPU 超过 8 个的机器,同样,唯一可以扩展的方法是水平扩展。

总结

我们感谢社区提供的来自新一代多线程项目的新鲜、有趣的想法和技术。甚至有可能,其中一些概念将来会融入 Redis(比如我们已经开始研究的 io_uring,更现代的字典,更战术的线程使用等)。但就目前而言,我们不会放弃 Redis 提供的无共享、多进程架构的基本原则。这种设计提供了最佳的性能、可扩展性和弹性,同时还支持内存中实时数据平台所需的各种部署架构。

附录 Redis 7.0 与 Dragonfly 基准测试细节

基准测试摘要

版本
目标
  • 验证 Dragonfly 的结果是否可重复,并确定获取这些结果的完整条件(鉴于 memtier_benchmark、操作系统版本等方面存在一些配置缺失……)更多信息请参见 此处
  • 确定在 AWS c6gn.16xlarge 实例上可实现的最佳 OSS Redis 7.0.0 集群性能,以匹配 Dragonfly 的基准测试
客户端配置
  • 鉴于每个 memtier_benchmark 线程都连接到所有分片,因此 OSS Redis 7.0 解决方案需要与 Redis 集群建立更多连接
  • OSS Redis 7.0 解决方案在两个 memtier_benchmark 进程运行基准测试但位于同一客户端 VM 上时(以匹配 Dragonfly 基准测试)取得了最佳结果
资源利用率和最佳配置
  • OSS Redis 集群在 40 个主分片时取得了最佳结果,这意味着 VM 上有 24 个备用 vCPU。虽然机器没有得到充分利用,但我们发现增加分片数量并没有帮助,反而降低了整体性能。我们仍在研究这种行为。
  • 另一方面,Dragonfly 解决方案将 VM 的所有 64 个 vCPU 全部利用,达到 100% 的利用率。
  • 对于两种解决方案,我们都改变了客户端配置,以取得最佳结果。如下所示,我们成功地复制了大部分 Dragonfly 数据,甚至超过了管道等于 30 的最佳结果。
  • 这意味着我们有可能进一步提高 Redis 所取得的数字。 

最后,我们还发现,Redis 和 Dragonfly 都没有受到网络 PPS 或带宽的限制,因为我们已经确认,在 2 台使用的 VM(用于客户端和服务器,两者都使用 c6gn.16xlarge)之间,我们可以使用约 300B 的有效负载,对于 TCP 达到 > 10M PPS 和 >30 Gbps。

分析结果

  • GET 管道 1 子毫秒:
    • OSS Redis:4.43M 次操作/秒,平均值和 p50 都达到了亚毫秒级延迟。平均客户端延迟为 0.383 毫秒
    • Dragonfly 声称 4M 次操作/秒
      • 我们成功地复制了 3.8M 次操作/秒,平均客户端延迟为 0.390 毫秒 
    • Redis 与 Dragonfly 的比较——Redis 的吞吐量比 Dragonfly 声称的结果高 10%,比我们能够复制的 Dragonfly 结果高 18%
  • GET 管道 30
    • OSS Redis:22.9M 次操作/秒,平均客户端延迟为 2.239 毫秒
    • Dragonfly 声称 15M 次操作/秒
      • 我们成功地复制了 15.9M 次操作/秒,平均客户端延迟为 3.99 毫秒
    • Redis 与 Dragonfly 的比较——Redis 比 (Dragonfly 复制的结果) 高 43%,比 (Dragonfly 声称的结果) 高 52%
  • SET 管道 1 子毫秒:
    • OSS Redis:4.74M 次操作/秒,平均值和 p50 都达到了亚毫秒级延迟。平均客户端延迟为 0.391 毫秒
    • Dragonfly 声称 4M 次操作/秒
      • 我们成功地复制了 4M 次操作/秒,平均客户端延迟为 0.500 毫秒
    • Redis 与 Dragonfly 的比较——Redis 比 (我们复制了 Dragonfly 声称的结果) 高 19%
  • SET 管道 30
    • OSS Redis:19.85M 次操作/秒,平均客户端延迟为 2.879 毫秒
    • Dragonfly 声称 10M 次操作/秒
      • 我们成功地复制了 14M 次操作/秒,平均客户端延迟为 4.203 毫秒)
    • Redis 与 Dragonfly 的比较——Redis 比 (Dragonfly 复制的结果) 高 42%,比 (Dragonfly 声称的结果) 高 99%

memtier_benchmark 用于每个变化的命令

  • GET 管道 1 子毫秒
    • Redis
      • 2X: memtier_benchmark –ratio 0:1 -t 24 -c 1 –test-time 180 –distinct-client-seed -d 256 –cluster-mode -s 10.3.1.88 –port 30001 –key-maximum 1000000 –hide-histogram
    • Dragonfly
      • memtier_benchmark –ratio 0:1 -t 55 -c 30 -n 200000 –distinct-client-seed -d 256 -s 10.3.1.6 –key-maximum 1000000 –hide-histogram
  • GET 管道 30
    • Redis
      • 2X: memtier_benchmark –ratio 0:1 -t 24 -c 1 –test-time 180 –distinct-client-seed -d 256 –cluster-mode -s 10.3.1.88 –port 30001 –key-maximum 1000000 –hide-histogram –pipeline 30
    • Dragonfly
      • memtier_benchmark –ratio 0:1 -t 55 -c 30 -n 200000 –distinct-client-seed -d 256 -s 10.3.1.6 –key-maximum 1000000 –hide-histogram –pipeline 30
  • SET 管道 1 子毫秒
    • Redis
      • 2X: memtier_benchmark –ratio 1:0 -t 24 -c 1 –test-time 180 –distinct-client-seed -d 256 –cluster-mode -s 10.3.1.88 –port 30001 –key-maximum 1000000 –hide-histogram
    • Dragonfly
      • memtier_benchmark –ratio 1:0 -t 55 -c 30 -n 200000 –distinct-client-seed -d 256 -s 10.3.1.6 –key-maximum 1000000 –hide-histogram
  • SET 管道 30
    • Redis
      • 2X: memtier_benchmark –ratio 1:0 -t 24 -c 1 –test-time 180 –distinct-client-seed -d 256 –cluster-mode -s 10.3.1.88 –port 30001 –key-maximum 1000000 –hide-histogram –pipeline 30
    • Dragonfly
      • memtier_benchmark –ratio 1:0 -t 55 -c 30 -n 200000 –distinct-client-seed -d 256 -s 10.3.1.6 –key-maximum 1000000 –hide-histogram –pipeline 30

基础设施细节

我们对客户端(用于运行 memtier_benchmark)和服务器(用于运行 Redis 和 Dragonfly)使用了相同的 VM 类型,以下是规格

  • VM:
    • AWS c6gn.16xlarge
      • aarch64
      • ARM Neoverse-N1
      • 每个插槽的核心数:64
      • 每个核心的线程数:1
      • NUMA 节点数:1
  • 内核:Arm64 内核 5.10
  • 已安装内存:126GB