Redis为何如此之快?IO多路复用技术究竟有何神奇之处?

摘要:redis能够达到每秒10万+ QPS(每秒查询率)的极高性能,并非只因为它是“内存数据库”,而是由存储介质、线程模型、网络模型以及数据结构优化共同决定的。 以下是redis快的具体原因: 绝大部分请求在内存中完成 这是
redis能够达到每秒10万+ QPS(每秒查询率)的极高性能,并非只因为它是“内存数据库”,而是由存储介质、线程模型、网络模型以及数据结构优化共同决定的。 以下是redis快的具体原因: 绝大部分请求在内存中完成 这是 Redis 快的根本原因。相比于传统数据库(如 MySQL)需要从磁盘读取数据,Redis 直接操作RAM(内存)。 存储介质 访问速度(数量级) 延迟说明 内存 (RAM) 纳秒 (ns) 极快,就像从书桌上拿书。 固态硬盘 (SSD) 微秒 (μs) 较快,但比内存慢 1000 倍。 机械硬盘 (HDD) 毫秒 (ms) 慢,就像去图书馆借书。 Redis 避免了磁盘 I/O 产生的巨大开销,数据操作几乎是瞬时的。 纯粹的单线程模型 很多人误以为多线程才快,但 Redis 的核心处理逻辑是单线程的(主要指文件事件分路器处理请求的部分)。 没有上下文切换:多线程在切换执行流时需要保存和加载 CPU 寄存器状态,这会产生明显的性能损耗。 没有锁的竞争:在多线程环境下,为了保证数据安全,必须引入锁(如互斥锁)。Redis 单线程执行,天然避免了死锁和锁竞争带来的开销。 简单即高效:单线程代码逻辑更简单,也更容易维护。 注意: Redis6.0引入了多线程来处理网络I/O,但执行命令的核心逻辑依然是单线程的。 非阻塞I/O多路复用 (I/O Multiplexing) Redis 使用了I/O多路复用技术(如 Linux 下的 epoll)来处理大量的并发连接。 原理:Redis并不是为一个连接分配一个线程,而是让一个线程监控数千个连接的状态。只有当某个连接真正有数据发过来时,Redis才会去处理。 效果:即使有成千上万个客户端同时连接,Redis 也能像一个老练的服务员同时照顾几十桌客人一样,谁叫就服务谁,而不需要在桌子之间来回空跑。 针对性优化的底层数据结构 Redis的开发者对每种数据类型都进行了极致的底层优化,并没有简单地使用编程语言内置的结构。 SDS (简单动态字符串):相比 C 语言原生字符串,获取长度的时间复杂度从O(N)降到了O(1),且减少了内存分配次数。 跳表 (SkipList):为有序集合 (ZSet) 提供平衡树一般的查找效率,但实现更简单,支持范围查询更高效。 压缩列表 (ZipList) / 整型数组: 在数据量较小时使用紧凑存储,极大节省了内存开销,提高了 CPU 缓存命中率。 总结: Redis的快可以总结为:基于内存操作 + 单线程 + 多路复用的并发 + 极致优化的底层数据结构。 详细说一下I/O多路复用 I/O多路复用(I/O Multiplexing)是现代高性能网络服务器(如 Nginx, Redis, Node.js)的核心基石。简单来说,它是一种 让单个线程能够同时监控多个网络连接(文件描述符) 的技术。 I/O多路复用解决了“高并发下的线程开销问题”。 在没有这项技术前,我们要支撑 1 万个并发连接,可能需要启动1万个线程,这会导致内存耗尽和CPU频繁的上下文切换。 有了 I/O 多路复用(尤其是 epoll),我们可以用一个线程轻松管理成千上万个连接,极大提升了系统的吞吐量。 举例理解: 假设一家餐厅有 100 桌客人: 阻塞 I/O (Blocking I/O): 一个服务员盯一桌客人。客人不点菜,服务员就死等。要服务 100 桌,就得请 100 个服务员。(开销巨大,线程切换成本高) 非阻塞 I/O (Non-blocking I/O): 一个服务员在 100 桌之间不停轮询:“点菜吗?”“不点。”“点菜吗?”“不点。” (效率低下,CPU 全在跑无意义的询问) I/O 多路复用: 服务员在前台放一个呼叫器。哪桌客人想点菜了,就按一下呼叫器,呼叫器亮起对应的桌号。服务员只需要盯着这个呼叫器,哪桌亮了去哪桌。 (这就是 I/O 多路复用) 三种核心实现机制 在Linux中,I/O 多路复用经历了从select 到 poll 再到 epoll的演进。 select:select 是最早的实现。它维护一个存放文件描述符(FD)的集合。 工作方式:每次调用都要把整个集合从用户态拷贝到内核态,内核线性扫描所有 FD。 缺点:有1024的数量限制(硬编码)。由于是线性扫描,时间复杂度为 O(n),连接越多越慢。 poll:基本解决了数量限制问题。 工作方式:使用链表存储 FD。 缺点:依然需要遍历整个集合来找出哪个 FD 就绪,性能随连接数增加而线性下降。 epoll (Linux的终极武器) epoll是目前Linux下处理百万级别并发的首选。
阅读全文