本页面正在审查中。 本页面可能不正确,包含无效链接,和/或需要技术审查。未来它可能会有重大更改或被完全删除。
Valkey 与其他键值存储有什么不同?
- Valkey 在键值数据库中的演进路径不同,它的值可以包含更复杂的数据类型,并对这些数据类型定义了原子操作。Valkey 的数据类型与基本数据结构紧密相关,并以这种方式直接暴露给程序员,没有额外的抽象层。
- Valkey 是一个内存数据库,但同时支持磁盘持久化,因此它代表了一种不同的权衡:在数据集合不能大于内存的限制下,实现了极高的写入和读取速度。内存数据库的另一个优势是,复杂数据结构的内存表示比磁盘上的相同数据结构更容易操作,因此 Valkey 可以在内部复杂性很小的情况下完成很多工作。同时,两种磁盘存储格式(RDB 和 AOF)不需要适用于随机访问,因此它们紧凑且始终以追加方式生成(即使 AOF 日志轮换也是追加操作,因为新版本是从内存中的数据副本生成的)。然而,这种设计也涉及与传统磁盘存储不同的挑战。由于主要数据表示在内存中,Valkey 操作必须小心处理,以确保磁盘上始终有数据集合的更新版本。
Valkey 的内存占用是多少?
举几个例子:
- 一个空实例大约占用 3MB 内存。
- 100 万个小键 -> 字符串值对大约占用 85MB 内存。
- 100 万个键 -> 散列值(表示一个包含 5 个字段的对象)大约占用 160MB 内存。
测试您的用例很简单。使用 valkey-benchmark
工具生成随机数据集,然后使用 INFO memory
命令检查所占用的空间。
为什么 Valkey 将其整个数据集保存在内存中?
过去,开发人员曾尝试使用虚拟内存和其他系统来允许大于 RAM 的数据集,但最终我们很高兴能做好一件事:数据从内存中提供,磁盘用于存储。因此,目前没有为 Valkey 创建基于磁盘后端(on-disk backend)的计划。毕竟,Valkey 的大部分特性都是其当前设计的直接结果。
如果您的真正问题不是所需的总 RAM,而是需要将数据集拆分到多个 Valkey 实例中,请查阅本文档中的分区页面以获取更多信息。
可以将 Valkey 与基于磁盘的数据库一起使用吗?
是的,一种常见的设计模式是将写入密集的小数据(以及您需要 Valkey 数据结构来高效建模问题的数据)放入 Valkey 中,并将大数据块放入 SQL 或最终一致的磁盘数据库中。类似地,有时 Valkey 也被用于将磁盘数据库中存储的相同数据子集的另一个副本加载到内存中。这可能看起来类似于缓存,但实际上这是一种更高级的模型,因为通常 Valkey 数据集会与磁盘数据库数据集一起更新,而不是在缓存未命中时才刷新。
如何减少 Valkey 的总体内存使用量?
一个好的做法是在将逻辑数据模型映射到 Valkey 中的物理数据模型时考虑内存消耗。这些考虑因素包括使用特定的数据类型、键模式和规范化。
除了数据建模之外,更多信息请查阅内存优化页面。
如果 Valkey 内存不足会发生什么?
Valkey 具有内置保护机制,允许用户通过配置文件中的 maxmemory
选项设置内存使用上限。如果达到此限制,Valkey 将开始对写入命令返回错误(但会继续接受只读命令)。
您还可以配置 Valkey 在达到最大内存限制时逐出键。有关更多信息,请参阅逐出策略文档。
Linux 上后台保存失败并出现 fork() 错误?
简短回答:echo 1 > /proc/sys/vm/overcommit_memory
:)
现在是详细解释
Valkey 的后台保存机制依赖于现代操作系统中 fork
系统调用的写时复制(copy-on-write)语义:Valkey 会 fork(创建一个子进程),该子进程是父进程的精确副本。子进程将数据库转储到磁盘上,最后退出。理论上,作为副本的子进程应该占用与父进程一样多的内存,但实际上,由于大多数现代操作系统实现的写时复制语义,父进程和子进程将共享公共内存页面。只有当页面在子进程或父进程中发生更改时,页面才会被复制。由于理论上在子进程保存期间所有页面都可能发生变化,Linux 无法提前知道子进程将占用多少内存,因此如果 overcommit_memory
设置为零,除非有足够的空闲 RAM 来真正复制所有父内存页面,否则 fork 将失败。如果您有一个 3 GB 的 Valkey 数据集而只有 2 GB 的空闲内存,它将失败。
将 overcommit_memory
设置为 1 会告诉 Linux 放松并以更乐观的分配方式执行 fork,这正是您对 Valkey 所期望的。
您可以参考 proc(5) 手册页以了解可用值的解释。
Valkey 的磁盘快照是原子的吗?
是的,Valkey 后台保存过程总是在服务器未执行命令时进行 fork 操作,因此每个在 RAM 中被报告为原子的命令,从磁盘快照的角度来看也是原子的。
Valkey 如何利用多个 CPU 或核心?
启用 I/O 线程以将客户端通信卸载到线程。在 Valkey 8 中,I/O 线程实现已被重写并大幅改进。从客户端读取命令和写回响应会占用大量 CPU 时间。通过将此工作卸载到单独的线程,主线程可以专注于执行命令。
您还可以在同一台机器上启动多个 Valkey 实例,并将它们组合成一个集群。
单个 Valkey 实例可以存储的最大键数是多少?Hash、List、Set 和 Sorted Set 中元素的最大数量是多少?
Valkey 可以处理多达 232 个键,并且在实践中已经过测试,每个实例至少可以处理 2.5 亿个键。
每个 hash、list、set 和 sorted set 都可以容纳 232 个元素。
换句话说,您的限制很可能是系统中可用的内存。
为什么我的副本键数量与主实例不同?
如果您使用具有有限生存时间(Valkey 过期)的键,这是正常行为。原因如下:
- 主实例在与副本的首次同步时生成 RDB 文件。
- RDB 文件将不包括在主实例中已过期但仍存在于内存中的键。
- 这些键即使在逻辑上已过期,仍存在于 Valkey 主实例的内存中。它们将被视为不存在,其内存将在之后回收,可以是增量回收,也可以是在访问时显式回收。虽然这些键在逻辑上不属于数据集,但它们会计算在
INFO
输出和DBSIZE
命令中。 - 当副本读取主实例生成的 RDB 文件时,这组键将不会被加载。
因此,对于拥有许多过期键的用户来说,在副本中看到更少的键是很常见的。然而,从逻辑上讲,主实例和副本将具有相同的内容。
Linux 基金会为何启动 Valkey 项目?
阅读Valkey 的历史。