来源:InfoQ、整理 | 钰莹、Tina
回击就代表输了?!
它绝对代表了现实世界中普通用户运行 Redis 的方式。“在单台机器上运行集群,只是为了能够使用超过 1 个 core" 是额外的复杂性,人们只有在别无选择的情况下才会这样做,如果竞争者无论有多少个 core 都能 “just works",那么最好能有更容易的设置。
“Redis 投入如此多的工程精力来写这么一篇文章,还对 Reids/Dragonfly 进行了基准测试,这是对 Dragonfly 的极大赞美。”“我很高兴 Redis 发了这篇文章,因此我必须要去了解一下 Dragonfly,它看起来很棒。”
使用一套完全无共享的架构实现纵向与横向线性扩展。与纯纵向扩展的多线程架构相比,这套方案能始终提供更好的架构灵活性。
提高复制速度,因为复制操作是跨多个进程并发完成的。
从虚拟机故障中快速恢复。因为新虚拟机的 Redis 实例将同时填充来自多个外部 Redis 实例的数据。
在出于复制、快照保存、Append Only File(AOF)重写等目的进行 Redis 分叉时,既享受边写边复制的好处,又无需承担繁重的内存开销。若非如此,我们(或客户)将需要支付昂贵的资源成本。
为了轻松管理整个集群,我们希望每个 Redis 实例都保持在较小体量,借此加快迁移分片、重新分片、扩展和重新均衡等的执行速度。
更佳弹性——我们在集群中使用的节点越多,整个集群的健壮性就越强。例如,如果您在三节点集群上运行数据集,且其中一个节点发生降级,则代表有三分之一的集群无法运行;但如果是在九节点集群上运行数据集,同样是其中一个节点发生降级,则只有九分之一的集群无法运行。
易于扩展——在横向扩展系统当中,向集群添加一个额外节点、并将数据集的一部分迁移到其中要容易得多。与之对应,在纵向扩展系统中,我们只能直接引入一个更大的节点并复制整个数据集……这是个漫长的过程,而且期间随时有可能闹出麻烦。
逐步扩展更具成本效益——纵向扩展,尤其是云环境下的纵向扩展,往往对应高昂的成本。在多数情况下,即使只需要向数据集内添加几 GB 内容,也需要将实例大小翻倍。
高吞吐——在 Redis,我们看到很多客户会在小型数据集上运行高吞吐量工作负载,即具有极高的网络带宽及 / 或每秒数据包(PPS)需求。我们以每秒操作数 100 万 + 的 1 GB 大小数据集为例,相较于使用单节点 c6gn.16xlarge 集群(128 GB 内存、64 个 CPU 加 100 Gbps 传输带宽,每小时使用成本 2.7684 美元),三个 c6gb.xlarge 节点(8 GB 内存、4 个 CPU 外加最高 25 Gbps 传输带宽,每小时 0.1786 美元)构成的集群能够将运行成本拉低 20%,而且健壮性反而更高。既然成本效益出色、弹性更强且吞吐量反超,那横向扩展无疑就是比纵向扩展更好的选择。
贴近 NUMA 架构——纵向扩展还要求使用能容纳更多核心和大容量 DRAM 的双插槽服务器;相比之下,Redis 这样的多处理架构其实更适应 NUMA 架构,因为其行为特征就接近一种由多个较小节点组成的网络。但必须承认,NUMA 跟多线程架构之间也有天然冲突。根据我们在其他多线程项目中的经验,NUMA 可能令内存数据存储的性能降低达 80%。
存储吞吐量限制——AWS EBS 等外部磁盘的扩展速度,显然不及内存和 CPU。事实上,云服务商会根据所使用设备的类型添加存储吞吐量限制。因此,避免吞吐量限制、满足数据高持久性要求的唯一办法,就是使用横向扩展——即添加更多节点和更多的配套网络附加磁盘。
临时磁盘——临时磁盘是一种将 Redis 运行在 SSD 上的绝佳方式(其中 SSD 用于替代 DRAM,而非充当持久存储介质),能够在保持 Redis 极高速度的同时将数据库成本保持在磁盘级水平。但临时磁盘也有其上限,一旦逼近这一上限,我们还需要进一步扩展容量——这时候,更好的办法仍然是添加更多节点、引入更多临时磁盘。所以,横向扩展继续胜出。
商品硬件——最后,我们的很多客户会在本地数据中心、私有云甚至是小型边缘数据中心内运行 Redis。在这类环境中,绝大多数设备内存不超过 64 GB、CPU 不超过 8 个,所以唯一可行的扩展方式就只有横向扩展。
我们使用 Redis 7.0.0,直接通过源码构建
Dragonfly 使用的则是构建自 https://github.com/Dragonfly/dragonfly#building-from-source 的 6 月 3 日版源码(hash=e806e6ccd8c79e002f721a1a5ecb847bd7a06489)
验证 Dragonfly 公布的结果是否可重现,并确定检索结果的完整条件(鉴于 memtier_benchmark、操作系统版本等信息有所缺失)
确定 AWS c6gn.16xlarge 实例上可实现的最佳 OSS Redis 7.0.0 集群性能,并与 Dragonfly 的基准测试结果相比较
OSS Redis 7.0 解决方案需要大量接入 Redis 集群的开放连接,因为每个 memtier_benchmark 线程都需要连接到所有分片
OSS Redis 7.0 解决方案在使用两个 memtier_benchmark 进程时成绩最好,而且为了与 Dragonfly 基准相适应,这两个进程运行在同样的客户端虚拟机上
OSS Redis 集群在 40 个主分片的配置下性能表现最佳,对应的就是虚拟机上有 24 个备用 vCPU。虽然设备资源仍未得到全部利用,但我们发现继续增加分片数量已经没有意义,反而会拉低整体性能。我们仍在调查具体原因。
另一方面,Dragonfly 解决方案彻底耗尽了虚拟机性能,所有 64 上 vCPU 均达到了 100% 利用率。
在两种解决方案中,我们调整了客户端配置以实现最佳结果。如下所示,我们成功重现了大部分 Dragonfly 基准数据,甚至在 30 通道条件下得出了比项目方更高的测试成绩。
本次测试强调与 Dragonfly 测试环境保持一致,如果调整测试环境,Redis 的成绩还有望进一步提升。
OSS Redis:每秒 443 万次操作,其中延迟平均值与第 50 百分位值均达到亚毫秒级别。平均客户端延迟为 0.383 毫秒。
Dragonfly 声称每秒 400 万次操作:
我们成功重现至每秒 380 万次操作,平均客户端延迟为 0.390 毫秒
Redis 对 Dragonfly——Redis 吞吐量比 Dragonfly 声称的结果高出 10%,比我们成功重现的 Dragonfly 结果高 18%。
OSS Redis:每秒 2290 万次操作,客户端平均延迟为 2.239 毫秒
Dragonfly 声称每秒可达 1500 万次操作:
我们成功重现了每秒 1590 万次操作,客户端平均延迟为 3.99 毫秒
Redis 对 Dragonfly——与 Dragonfly 的重现结果和声称结果相比,Redis 分别胜出 43% 和 52%
OSS Redis:每秒 474 万次操作,延迟平均值与第 50 百分位值均达到亚毫秒级。客户端平均延迟为 0.391 毫秒
Dragonfly 声称每秒 400 万次操作:
我们成功重现了每秒 400 万次操作,客户端平均延迟为 0.500 毫秒
Redis 对 Dragonfly——与 Dragonfly 的重现结果和声称结果相比,Redis 均胜出 19%
OSS Redis:每秒 1985 万次操作,客户端平均延迟为 2.879 毫秒
Dragonfly 声称每秒 1000 万次操作:
我们成功重现了每秒 1400 万次操作,客户端平均延迟为 4.203 毫秒
Redis 对 Dragonfly——与 Dragonfly 的重现结果和声称结果相比,Redis 分别胜出 42% 和 99%
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
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
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
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
虚拟机:AWS c6gn.16xlarge
aarch64
ARM Neoverse-N1
每插槽核心数: 64
每核心线程数: 1
NUMA 节点数: 1
核心版本: Arm64 Kernel 5.10
安装内存: 126 GB
推荐阅读
IntelliJ项目迁移到Java 17!2022.3 版本开始必须Java 17! Jenkins + Docker 一键自动化部署 SpringBoot 项目 微软出手,拯救“四分五裂”的Markdown!
你好,我是程序猿DD,10年开发老司机、阿里云MVP、腾讯云TVP、出过书创过业、国企4年互联网6年。从普通开发到架构师、再到合伙人。一路过来,给我最深的感受就是一定要不断学习并关注前沿。只要你能坚持下来,多思考、少抱怨、勤动手,就很容易实现弯道超车!所以,不要问我现在干什么是否来得及。如果你看好一个事情,一定是坚持了才能看到希望,而不是看到希望才去坚持。相信我,只要坚持下来,你一定比现在更好!如果你还没什么方向,可以先关注我,这里会经常分享一些前沿资讯,帮你积累弯道超车的资本。