2017-07-28 43 views
1

我想了解Redis的基础知识。 随处可见的Redis是单线程的,它使事物变得原子化。但我无法想象这是如何在内部工作的。我有以下疑问。为什么Redis是单线程的(事件驱动)

不是我们设计一个服务器单线程,如果它是IO绑定应用程序(如Node.js),其中线程在启动IO操作后可以释放另一个请求并在IO操作完成后将数据返回给客户端(提供并发)。但是在redis的情况下,所有的数据都可以在主内存中使用,我们根本不打算进行IO操作。那么为什么Redis是单线程的呢?如果第一个请求花费很多时间,剩下的请求将不得不保留等候?

+0

[This answer](https://stackoverflow.com/a/10495458/2395796)解释得很好。 –

回答

6

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命令进行测试。

+0

如果我错了,请纠正我。假设Redis获得两个请求Req1,其中IO绑定(花费太多时间),然后Req2到来,Req2需要非常少的IO,那么Req2将立即提供,但是如果Req1是CPU密集型(在Redis中的某个大型列表中搜索),Req2将不得不等待直到Req1没有完成。 – Nishat

+0

@carl伟大而正确 - 请参阅我的附录(或者可能是新时代的前奏?)虽然 –

+0

@Nishat你是正确的,但在将来的版本中可能会改变 –

6

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

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

+1

也就是说,很长的运行请求可能会允许其他请求在同一时间运行。 –