Redis 之所以能以极快的速度处理海量请求,主要归功于以下几个核心设计:
1. 纯内存操作
Redis 的所有数据都存储在内存中,而内存的读写速度是纳秒级(约为磁盘的十万到百万倍)。没有磁盘 I/O 的瓶颈,这是 Redis 快的最根本原因。即使持久化(RDB/AOF)也是异步或通过子进程完成,不阻塞主线程。
2. 单线程模型 + 非阻塞 I/O 多路复用
Redis 的核心命令执行是单线程的,这避免了多线程环境下的上下文切换开销和锁竞争。
- 为什么单线程还能处理高并发?
Redis 采用了 I/O 多路复用机制(如 Linux 下的epoll),用一个线程同时监听多个 socket 的可读/可写事件,将事件分派给对应处理程序。这样既能高效处理大量客户端连接,又保证了命令执行的原子性和简单性。 - 注:Redis 6.0 引入了多线程网络 I/O,用于处理网络数据的读写,但命令执行依然是单线程。这既提升了网络吞吐量,又保留了单线程的简洁性。
3. 高效的数据结构
Redis 不是简单的键值对存储,而是提供了多种底层优化过的数据结构:
- SDS(简单动态字符串) :替代 C 字符串,支持 O(1) 获取长度、杜绝缓冲区溢出、减少修改时内存重分配。
- 压缩列表(ziplist) 、跳跃表(skiplist) 、字典(dict) 等都经过精心设计,在时间复杂度和内存占用之间取得平衡。
- 例如,ZSet 底层同时使用哈希表和跳跃表,既能 O(1) 获取分数,又能 O(logN) 进行范围查询。
4. 非阻塞 I/O 与事件驱动
Redis 使用单线程事件循环(ae 事件库)处理所有客户端请求。当 socket 可读/可写时,事件循环才去处理,不会因为某个慢操作而阻塞其他连接(除非执行 O(N) 复杂命令)。
- 这种模型允许 Redis 在单核 CPU 上支撑数万并发连接。
5. 避免无关操作
- 没有事务锁、没有多线程同步开销。
- 持久化(RDB、AOF)通过
fork子进程异步完成,主进程继续服务。 - 淘汰过期 key 采用惰性删除 + 定期删除,不会主动扫描全库。
6. 使用 C 语言实现,接近硬件
Redis 使用 C 语言编写,编译后直接运行在操作系统上,没有虚拟机或解释器的额外开销,能够充分利用 CPU 指令和内存特性。
总结:为什么 Redis 快?
| 因素 | 说明 |
|---|---|
| 内存存储 | 数据在内存中,读写速度是磁盘的几十万倍 |
| 单线程模型 | 避免锁竞争和上下文切换,简化设计 |
| I/O 多路复用 | 非阻塞 I/O,单线程管理大量连接 |
| 高效数据结构 | 底层数据结构针对性能优化 |
| 异步持久化 | 持久化不阻塞主线程 |
| C 语言实现 | 接近底层,性能极高 |