在尝试掌握 Redis 的一些基础知识时,我发现了一篇有趣的 博客文章 .
作者指出:
Redis 是单线程的 epoll/kqueue,并且在 I/O 并发方面可以无限扩展。
我肯定误解了整个线程的事情,因为我发现这个说法令人费解。如果一个程序是单线程的,它如何同时执行任何操作?如果服务器是单线程的,为什么 Redis 操作是原子的这么好?
有人可以解释一下这个问题吗?
这取决于你如何定义并发。
在服务器端软件中,并发和并行通常被视为不同的概念。在服务器中,支持并发 I/O 意味着服务器能够通过仅使用一个计算单元执行与这些客户端相对应的多个流程来为多个客户端提供服务。在这种情况下,并行性意味着服务器能够同时执行多项操作(使用多个计算单元),这是不同的。
例如,调酒师可以同时照顾多名顾客,但他一次只能准备一种饮料。所以他可以提供没有并行性的并发。
这个问题已经在这里争论过: 并发和并行有什么区别?
另请参阅 Rob Pike 的此演示。
单线程程序绝对可以通过使用 I/O(解)复用机制和事件循环(这就是 Redis 所做的)来提供 I/O 级别的并发性。
并行是有代价的:在现代硬件上可以找到多个套接字/多个内核,线程之间的同步非常昂贵。另一方面,像 Redis 这样的高效存储引擎的瓶颈往往是网络,远远早于 CPU。因此,隔离事件循环(不需要同步)被视为构建高效、可扩展服务器的良好设计。
Redis 操作是原子的这一事实只是单线程事件循环的结果。有趣的一点是原子性是免费提供的(它不需要同步)。用户可以利用它来实现乐观锁定和其他模式,而无需支付同步开销。
好的,Redis 在用户级是单线程的,OTOH,所有异步 I/O 都由内核线程池和/或分层驱动程序支持。
对于某些人来说,“并发”包括将网络事件分发到套接字状态机。 它是单线程的,在一个核心上运行(在用户级别),所以我不会将其称为并发。 其他的则不同.. '
在 I/O 并发性方面无限扩展'只是为了节省事实。 如果他们说“可以比每个客户端一个线程更好地扩展,只要客户端要求不高”,他们可能会更加相信,尽管他们可能会觉得有必要添加“对其他异步解决方案的重负载感到震惊”在用户级别使用所有核心”。