
Valkey 8.1:持续提供增强的性能和可靠性
Valkey 社区很高兴推出 Valkey 8.1 新版本,这是一个次要版本更新,旨在进一步提升所有 Valkey 安装的性能、可靠性、可观察性和可用性,超越 Valkey 8.0。
在这篇博客中,我们将深入探讨 Valkey 8.1 中的一些新功能以及它们如何能让您的应用程序受益。
性能
Valkey 8.1 引入了多项性能改进,可减少延迟、提高吞吐量并降低内存使用。
新的哈希表
导致多项性能改进的主要变化是新的哈希表实现,它既用作 Valkey 中的主键值存储,也用于 Hash、Set 和 Sorted Set 数据类型的实现。
新的哈希表实现是对原有哈希表的完全重写。新设计采用了多种现代设计技术,以减少存储每个对象所需的分配数量,从而减少随机内存访问次数,同时节省内存。
结果是,我们观察到不带 TTL 的键值对每个键值对减少了约 20 字节,带 TTL 的键值对最多减少了 30 字节。在不使用 I/O 线程的情况下,新实现还帮助 Valkey 服务器的吞吐量比 8.0 版本在管道工作负载下提高了约 10%。
您可以在关于此实现的专门博客文章中了解更多设计和结果。
迭代器预取
遍历键集键在各种场景中都会发生,例如当 Valkey 节点需要将所有键和值发送给新连接的副本时。
在 Valkey 8.1 中,迭代功能通过使用内存预取技术得到了改进。
这意味着当一个元素即将返回给调用者时,其桶和元素在迭代前一个桶时就已经被加载到 CPU 缓存中。
这使得迭代器比不使用预取时快 3.5 倍,从而减少了向新连接副本发送数据所需的时间。
KEYS
等命令也受益于此优化。
I/O 线程改进
继 8.0 版本中添加的 I/O 线程改进之后,8.1 版本中将更多操作卸载到 I/O 线程池,从而提高了某些操作的吞吐量和降低了延迟。
在新版本中,TLS 连接现在能够将 TLS 协商卸载到 I/O 线程。这一改变将接受新连接的速度提高了约 300%。
TLS 连接处理中的其他开销来源已被识别,即在主事件线程中调用的 SSL_pending()
和 ERR_clear_error()
函数。通过将这些函数卸载到 I/O 线程池,某些操作的吞吐量得到了改善。例如,观察到 SET
操作的吞吐量提高了 10%,GET
操作的吞吐量提高了 22%。
8.1 版本中通过将副本上的复制流读取卸载到 I/O 线程池,从而提高了复制流量效率,这意味着它们可以处理更多的读取流量。在主节点上,复制流写入现在已卸载到 I/O 线程池。
复制改进
通过在无盘复制时移除冗余的 CRC 校验和,启用 TLS 的完全同步速度提高了 18%。
fork 写时复制内存开销减少了高达 47%
有序集合、HyperLogLog 和位计数优化
ZRANK
命令在排行榜操作中是一个常用的用例,已得到优化,根据有序集合的大小,其执行速度最高可提高 45%。
ZADD
和其他涉及浮点数的命令通过 fast_float
进行了优化,以使用 SIMD 指令解析浮点数。此优化需要 C++ 编译器,并且目前是编译时可选择启用的功能。
概率性的 HyperLogLog 是另一种出色的数据类型,用于在超大型数据集中计算唯一元素,无论元素数量多少,都仅使用 12KB 内存。通过使用现代 CPU x86 的高级矢量扩展,Valkey 8.1 在 HyperLogLog 数据类型的 PFMERGE
和 PFCOUNT
等操作中可以实现 12 倍的速度。
同样,在 x86 上使用 AVX2,BITCOUNT
操作的性能提高了高达 514%。
主动碎片整理改进
主动碎片整理已得到改进,以消除大于 1ms 的延迟(https://github.com/valkey-io/valkey/pull/1242)。碎片整理周期时间已缩短至 500us(且频率增加),从而使延迟更具可预测性,并显著降低了尾部延迟。
在存在长时间运行的命令时,还引入了防饥饿保护。如果一个慢命令延迟了碎片整理周期,碎片整理过程将按比例运行更长时间,以确保达到配置的 CPU 使用率。考虑到慢命令的存在,按比例增加的额外时间对延迟的影响微乎其微。
可观察性
Valkey 8.1 在系统行为的可观察性方面也有多项改进。
日志改进
Valkey 8.1 为日志文件条目格式和时间戳记录方式带来了新选项。这使得日志收集系统更容易消费日志文件。
日志文件条目的格式由 log-format
参数控制,默认值为现有格式:
legacy
:默认的传统日志格式logfmt
:一种结构化日志格式;请参阅 https://www.brandur.org/logfmt
日志文件条目时间戳的格式由 log-timestamp-format
参数控制,默认值为现有格式:
legacy
:默认格式iso8601
:ISO 8601 扩展日期和时间,带时区,格式为 yyyy-mm-ddThh:mm:ss.sss±hh:mmmilliseconds
:自 Unix 纪元以来的毫秒数
注意:同时使用 logfmt
和 iso8601
格式会占用大约 60% 的额外空间,因此在实施这些格式时应考虑磁盘空间。
将慢日志扩展到命令日志
Valkey 长期以来都具备根据 slowlog-log-slower-than
参数设置的阈值在执行时记录慢命令的能力,并保留最后 slowlog-max-len
条目。作为故障排除的有用工具,它没有考虑到应用程序的整体往返时间或对网络使用的影响。随着 Valkey 8.1 中新增 COMMANDLOG
功能,现在可以记录大型请求和回复,这为用户提供了端到端延迟的良好可见性。
改进的延迟洞察
Valkey 具有内置的延迟监控框架,当通过 latency-monitor-threshold
延迟监控器启用时,该框架会对延迟敏感的代码路径(例如 fork)进行采样。
新功能为 LATENCY LATEST
命令增加了额外的指标,该命令报告已收集到的最新延迟事件。Valkey 8.1 中的额外信息报告了记录的延迟总和以及此事件记录的峰值数量。这些附加字段使用户能够更好地了解这些延迟事件发生的频率以及它们对系统造成的总影响。
可扩展性
Valkey 以其可扩展性功能而闻名。复杂的模块系统允许使用作为外部模块开发的新功能来扩展核心系统。
可编程性
在 Valkey 8.1 中,模块系统 API 得到了扩展,支持将新的脚本引擎开发为外部模块。
这个新的 API 为开发新的语言和运行时替代方案打开了大门,以取代 Valkey 核心在使用 EVAL
和 FCALL
命令时支持的基于 Lua 的脚本。
在 Valkey 的未来版本中,我们期待出现新的脚本引擎。一个很好的候选是基于 WASM 的脚本引擎,它允许 EVAL
脚本用 Lua 以外的其他语言编写,并在更安全的沙盒环境中执行。
对于现有的 Lua 脚本也有益处,因为可以轻松插入提供更好安全属性和/或更好性能的新 Lua 运行时。
打算为 Valkey 构建新脚本引擎的开发者应查阅模块 API 文档。
其他亮点
条件更新
这项新功能允许 Valkey 用户在使用 SET
命令时执行条件更新,即当给定的比较值与键的当前值匹配时。这不仅是开发人员的一项生活质量改进,因为他们不再需要将此条件添加到应用程序代码中,它还节省了先获取值再进行比较然后才执行 SET
的往返时间。当将可选的 GET
作为 SET IFEQ
的一部分使用时,无论它是否与比较值匹配,都会返回现有值。
结论
Valkey 8.1 持续创新和改进,透明地为用户带来更高的性能和可靠性。我们期待听到您使用 Valkey 8.1 取得的成就!更多详细信息请参阅 8.1 GA 版本的发布说明。
鸣谢
我们感谢所有为本次发布贡献代码的开发者!
- Alan Scherger (flyinprogrammer),
- Amit Nagler (naglera),
- Basel Naamna (xbasel),
- Ben Totten (bentotten),
- Binbin (enjoy-binbin),
- Caiyi Wu (Codebells),
- Danish Mehmood (danish-mehmood),
- Eran Ifrah (eifrah-aws),
- Guillaume Koenig (knggk),
- Harkrishn Patro (hpatro),
- Jacob Murphy (murphyjacob4),
- Jim Brunner (JimB123),
- Josef Šimánek (simi),
- Jungwoo Song (bluayer),
- Karthick Ariyaratnam (karthyuom),
- Karthik Subbarao (KarthikSubbarao),
- Lipeng Zhu (lipzhu),
- Madelyn Olson (madolson),
- Masahiro Ide (imasahiro),
- Melroy van den Berg (melroy89),
- Mikhail Koviazin (mkmkme),
- Nadav Gigi (NadavGigi),
- Nadav Levanoni (nadav-levanoni),
- Nikhil Manglore (Nikhil-Manglore),
- Parth Patel (parthpatel),
- Pierre (pieturin),
- Ping Xie (PingXie),
- Qu Chen (QuChen88),
- Rain Valentine (SoftlyRaining),
- Ran Shidlansik (ranshid),
- Ray Cao (RayaCoo),
- Ricardo Dias (rjd15372),
- Romain Geissler (Romain-Geissler-1A),
- Roman Gershman (romange),
- Roshan Khatri (roshkhatri),
- Rueian (rueian),
- Sarthak Aggarwal (sarthakaggarwal97),
- Seungmin Lee (sungming2),
- Shai Zarka (zarkash-aws),
- Shivshankar (Shivshankar-Reddy),
- Simon Baatz (gmbnomis),
- Sinkevich Artem (ArtSin),
- Stav Ben-Tov (stav-bentov),
- Stefan Mueller (muelstefamzn),
- Tal Shachar (talxsha),
- Thalia Archibald (thaliaarchi),
- Uri Yagelnik (uriyage),
- Vadym Khoptynets (poiuj),
- Viktor Szépe (szepeviktor),
- Viktor Söderqvist (zuiderkwast),
- Vu Diep (vudiep411),
- Wen Hui (hwware),
- Xuyang WANG (Nugine),
- Yanqi Lv (lyq2333),
- Yury Fridlyand (Yury-Fridlyand),
- Zvi Schneider (zvi-code),
- bodong.ybd (yangbodong22011),
- chx9,
- kronwerk,
- otheng (otheng03),
- secwall,
- skyfirelee (artikell),
- xingbowang (xingbowang),
- zhaozhao.zz (soloestoy),
- zhenwei pi(pizhenwei),
- zixuan zhao (azuredream),
- 烈香 (hengyoush),
- 风去幽墨 (fengquyoumo)