为什么 Redis 是单线程的(事件驱动)



我试图理解Redis的基础知识。 一个不断出现的是,Redis是单线程的,使事情原子化。但我无法想象这在内部是如何运作的。我有以下疑问。

如果它是IO绑定的应用程序(如Node.js(,我们不是设计一个服务器单线程吗,其中线程在启动IO操作后可以自由地用于另一个请求,并在IO操作完成后将数据返回给客户端(提供并发性(。但是在redis的情况下,所有数据都在主内存中可用,我们根本不会做IO操作。那么为什么 Redis 是单线程的呢?如果第一个请求花费大量时间,剩余的请求将不得不继续等待,会发生什么?

TL;DR:单线程使 redis 更简单,Redis 仍然是 IO 绑定的。

内存是 I/O。Redis 仍受 I/O 限制。当 redis 负载过重并达到每秒最大请求数时,它通常会缺乏网络带宽或内存带宽,并且通常不会占用太多 CPU。对于某些命令,情况并非如此,但对于大多数用例,redis 将受到网络或内存的严重 I/O 限制。

除非内存和网络速度突然提高几个数量级,否则单线程通常不是问题。如果您需要扩展到一个或几个线程之外(即:主<>从<->从设置(,那么您已经在查看 Redis 集群。在这种情况下,如果您不知何故 CPU 不足并希望最大化线程数,则可以为每个 CPU 核心设置一个集群实例。

我对 redis 源代码或内部不是很熟悉,但我可以看到使用单个线程如何轻松实现无锁原子操作。线程会使这变得更加复杂,并且似乎没有提供很大的优势,因为 redis 不受 CPU 限制。在 Redis 实例之上的级别实现并发似乎是一个很好的解决方案,Redis Sentinel 和 Redis Cluster 可以提供帮助。

当 redis 需要很长时间时,其他请求会发生什么情况?

当 redis 完成长请求时,这些其他请求将阻塞。如果需要,可以使用client-pause命令对此进行测试。

当然,正确答案是卡尔的。然而。

在 Redis v4 中,我们看到了从主要是单线程到有选择和谨慎的多线程转变的开始。模块和线程安全上下文就是一个例子。另外两个是新的UNLINK命令和ASYNC模式 用于FLUSHDB/FLUSHALL。未来的计划是将当前由主事件循环完成的更多工作(例如 IO 绑定任务(卸载到工作线程。

来自 redis 网站

Redis 主要使用单线程设计。这意味着单 进程使用一种称为 多路复用。这意味着 Redis 可以在 每个给定时刻,因此所有请求都按顺序提供服务。这 也与 Node.js 的工作方式非常相似。但是,这两种产品 通常不被认为是缓慢的。这部分是由于 完成单个请求的时间很短,但主要是 由于这些产品旨在不阻止系统调用,因此 作为从套接字读取数据或将数据写入套接字。

我说过 Redis 主要是单线程的,因为实际上从 Redis 2.4 开始,我们在 Redis 中使用线程是为了在后台执行一些缓慢的 I/O 操作,主要与磁盘 I/O 有关,但这并没有改变 Redis 使用单个线程为所有请求提供服务的事实。

内存无 I/O 操作

最新更新