Redis 常见问题解答

开始使用Redis时常见的问题

Redis与其他键值存储有何不同?

  • Redis在键值数据库中有着不同的发展路径,其中值可以包含更复杂的数据类型,并且在这些数据类型上定义了原子操作。Redis数据类型与基本数据结构密切相关,并且直接暴露给程序员,没有额外的抽象层。
  • Redis 是一种内存中但持久化到磁盘的数据库,因此它代表了一种不同的权衡,即在数据集不能大于内存的限制下实现了非常高的写入和读取速度。内存数据库的另一个优点是,与磁盘上的相同数据结构相比,复杂数据结构的内存表示更容易操作,因此 Redis 可以在内部复杂性较低的情况下完成很多工作。同时,两种磁盘存储格式(RDB 和 AOF)不需要适合随机访问,因此它们是紧凑的,并且总是以仅追加的方式生成(即使 AOF 日志轮换也是仅追加操作,因为新版本是从内存中的数据副本生成的)。然而,与传统的磁盘存储相比,这种设计也涉及不同的挑战。作为内存中的主要数据表示,必须小心处理 Redis 操作,以确保磁盘上始终有数据集的更新版本。

Redis的内存占用是多少?

给你一些例子(所有例子都是使用64位实例获得的):

  • 一个空实例使用约3MB的内存。
  • 1百万个小键 -> 字符串值对使用约85MB的内存。
  • 1百万个键 -> 哈希值,代表一个包含5个字段的对象,使用约160 MB的内存。

测试您的用例非常简单。使用redis-benchmark工具生成随机数据集,然后使用INFO memory命令检查使用的空间。

64位系统将比32位系统使用更多的内存来存储相同的键,特别是如果键和值很小的话。这是因为在64位系统中指针占用8个字节。但当然,优势在于你可以在64位系统中拥有大量内存,因此为了运行大型Redis服务器,64位系统或多或少是必需的。另一种选择是分片。

为什么Redis将其整个数据集保存在内存中?

过去,Redis开发者尝试了虚拟内存和其他系统,以允许大于RAM的数据集,但最终我们非常高兴能够做好一件事:从内存中提供数据,磁盘用于存储。因此,目前没有计划为Redis创建磁盘后端。毕竟,Redis的大部分特性都是其当前设计的直接结果。

如果你的实际问题不是所需的总内存,而是你需要将数据集分割到多个Redis实例中,请阅读本文档中的分区页面以获取更多信息。

Redis有限公司,这家赞助Redis开发的公司,已经开发了一个“Redis on Flash”解决方案,该方案采用RAM/闪存混合的方法来处理具有偏向访问模式的较大数据集。您可以查看他们的产品以获取更多信息,但此功能并非Redis社区版代码库的一部分。

你能将Redis与基于磁盘的数据库一起使用吗?

是的,一个常见的设计模式涉及将Redis中写入频繁的小数据(以及需要使用Redis数据结构以高效方式建模问题的数据)和大块数据放入SQL或最终一致的磁盘数据库中。同样,有时Redis用于在内存中存储磁盘数据库中存储的相同数据的子集的另一个副本。这可能看起来类似于缓存,但实际上是一种更高级的模型,因为通常Redis数据集会与磁盘数据库数据集一起更新,而不是在缓存未命中时刷新。

如何减少Redis的总体内存使用量?

一个好的做法是在将逻辑数据模型映射到Redis中的物理数据模型时考虑内存消耗。这些考虑包括使用特定的数据类型、键模式和规范化。

除了数据建模之外,内存优化页面中还有更多信息。

如果Redis内存耗尽会发生什么?

Redis 内置了保护机制,允许用户通过配置文件中的 maxmemory 选项设置内存使用的最大限制。如果达到这个限制,Redis 将开始对写命令返回错误(但仍会继续接受只读命令)。

你也可以配置Redis在达到最大内存限制时驱逐键。有关此功能的更多信息,请参阅驱逐策略文档

在Linux上后台保存因fork()错误而失败?

简短回答:echo 1 > /proc/sys/vm/overcommit_memory :)

现在是长的一个:

Redis 的后台保存方案依赖于现代操作系统中 fork 系统调用的写时复制语义:Redis 会 fork(创建一个子进程),该子进程是父进程的精确副本。子进程将数据库转储到磁盘上,最后退出。理论上,子进程应该使用与父进程相同的内存,因为它是父进程的副本,但实际上,由于大多数现代操作系统实现了写时复制语义,父进程和子进程将共享相同的内存页。只有当子进程或父进程中的页面发生变化时,页面才会被复制。由于理论上在子进程保存时所有页面都可能发生变化,Linux 无法提前知道子进程将占用多少内存,因此如果 overcommit_memory 设置为零,除非有足够的空闲 RAM 来真正复制所有父进程的内存页,否则 fork 将失败。如果你有一个 3 GB 的 Redis 数据集,而只有 2 GB 的空闲内存,它将失败。

overcommit_memory设置为1告诉Linux以更乐观的分配方式放松并执行fork,这确实是Redis所需要的。

您可以参考proc(5)手册页以了解可用值的解释。

Redis 磁盘快照是原子的吗?

是的,当服务器不在执行命令时,Redis的后台保存进程总是被分叉,因此从磁盘快照的角度来看,每个报告为在RAM中原子性的命令也是原子性的。

Redis 如何使用多个 CPU 或核心?

在Redis中,CPU成为瓶颈的情况并不常见,因为通常Redis受限于内存或网络。例如,在使用流水线操作时,运行在普通Linux系统上的Redis实例每秒可以处理100万个请求,因此如果你的应用程序主要使用O(N)或O(log(N))命令,它几乎不会使用太多的CPU。

然而,为了最大化CPU使用率,您可以在同一台机器上启动多个Redis实例,并将它们视为不同的服务器。在某些情况下,单台机器可能已经不够用了,所以如果您想使用多个CPU,您可以开始考虑一些早期分片的方法。

你可以在分区页面找到更多关于使用多个Redis实例的信息。

从4.0版本开始,Redis已经开始实现线程化操作。目前,这仅限于在后台删除对象和通过Redis模块实现的阻塞命令。对于后续版本,计划是使Redis越来越线程化。

单个Redis实例可以容纳的最大键数是多少?Hash、List、Set和Sorted Set中的最大元素数是多少?

Redis 可以处理多达 2^32 个键,并且在实践中测试过每个实例至少可以处理 2.5 亿个键。

每个哈希、列表、集合和有序集合都可以容纳2^32个元素。

换句话说,你的限制可能是系统中可用的内存。

为什么我的副本与其主实例的键数量不同?

如果您使用具有有限生存时间的键(Redis过期),这是正常行为。以下是发生的情况:

  • 主服务器在与副本的第一次同步时生成一个RDB文件。
  • RDB文件将不包括在主数据库中已过期但仍存在于内存中的键。
  • 这些键仍然存在于Redis主节点的内存中,即使它们在逻辑上已经过期。它们将被视为不存在,并且它们的内存将在稍后被回收,无论是逐步回收还是在访问时显式回收。虽然这些键在逻辑上不属于数据集的一部分,但它们会被计入INFO输出和DBSIZE命令中。
  • 当副本读取由主节点生成的RDB文件时,这组键将不会被加载。

因此,对于拥有许多过期密钥的用户来说,在副本中看到较少的密钥是很常见的。然而,从逻辑上讲,主节点和副本将具有相同的内容。

“Redis”这个名字从何而来?

Redis 是一个缩写,代表 远程 字典 服务器

为什么Salvatore Sanfilippo启动了Redis项目?

Salvatore最初创建Redis是为了扩展LLOOGG,一个实时日志分析工具。但在基本Redis服务器工作后,他决定与其他人分享这项工作,并将Redis转变为一个开源项目。

Redis 如何发音?

"Redis" (/ˈrɛd-ɪs/) 的发音类似于单词 "red" 加上单词 "kiss",但没有 "k"。

RATE THIS PAGE
Back to top ↑