共计 1677 个字符,预计需要花费 5 分钟才能阅读完成。
Redis 被广泛应用于缓存、分布式锁、排行榜、消息队列等高并发场景,因其极致的性能被誉为“速度之王”。但 Redis 的快并不是偶然,而是得益于一系列底层设计与实现上的精妙取舍。本文将系统剖析 Redis 为什么快,从内存模型、数据结构、线程模型、网络通信到协议设计,逐层揭示这款中间件的性能之源。
一、全内存操作:高性能的基础
Redis 将所有数据存储在内存中,完全摒弃了传统数据库依赖磁盘的 I/O 模型。内存的访问速度通常在纳秒级,而磁盘 I/O 即使是 SSD 也在毫秒级,两者相差百万倍。
- 读写延迟低
- 操作数据无磁盘 seek 与 flush
- 适合频繁访问、热点数据
当然,为了容错,Redis 提供了 RDB 和 AOF 两种持久化方式作为补充(后文详述)。
二、精心设计的数据结构:减少 CPU 和内存消耗
Redis内置的数据结构并非标准库直接使用,而是经过专门设计与优化的,以适应不同数据体量、访问模式和操作频率。
Redis 类型 | 底层结构 | 优化点概览 |
---|---|---|
String | SDS(Simple Dynamic String) | 支持预分配、空间重用、二进制安全 |
List | QuickList(ziplist + linkedlist) | 压缩节省内存,支持快速插入/弹出 |
Hash | ziplist / hashtable | 小量数据 ziplist,自动升级为 hashtable |
Set | intset / hashtable | 整数集合压缩,小集合优化 |
ZSet | 跳表(skiplist)+ 字典 | 高效支持范围查询与排序 |
三、单线程模型
Redis 使用单线程执行命令,避免了多线程带来的锁竞争、上下文切换和共享资源冲突。
多数系统因并发而慢,Redis 因单线程而快。
- 无需加锁:单线程内天然串行
- 操作原子:每个命令执行完整后再处理下一个
- 简洁逻辑:代码可维护性强、延迟更可控
多线程是彻底禁止的吗?
并非如此。Redis 在部分场景中使用多线程:
- RDB/AOF 后台持久化使用子进程
- AOF 重写由子进程并行执行
- Redis 6 引入多线程 I/O 模型,加速数据读写(非命令执行)
四、I/O 多路复用:支撑海量连接的能力
Redis 使用 I/O 多路复用技术处理并发连接,基于操作系统提供的高性能事件机制:
- Linux:
epoll
- macOS:
kqueue
- Windows:
select
一般都部署在linux,所以重点关注epoll
epoll 优势:
- 支持 10 万连接级别的并发
- 事件驱动、非阻塞
- 使用注册回调的方式处理事件,无需频繁轮询
五、惰性 + 定期删除机制:高效内存回收策略
Redis 采用组合式的过期键清理机制:
- 惰性删除:访问时才判断是否过期(低开销)
- 定期删除:后台周期随机抽样清理(控制资源使用)
- 内存淘汰策略:触发
maxmemory
时执行 LRU、LFU 或 TTL 策略
通过分摊删除代价、避免集中释放,保证了内存管理的实时性与系统平稳性。
六、持久化机制设计合理,避免主线程阻塞
Redis 持久化并不影响核心性能,所有重操作都在子进程中完成:
- RDB 快照:fork 子进程生成
.rdb
文件 - AOF 日志:主线程写缓冲区,后台刷盘
- AOF 重写:子进程基于当前数据生成新日志文件
由于主进程不会阻塞,Redis 可持续提供高性能服务,同时保证数据恢复能力。
七、总结:Redis 快的背后是系统级工程艺术
Redis 的高性能并非简单的某个点做得好,而是整体架构、内存控制、协议设计和事件调度的系统级优化成果。
模块 | 性能优化点 |
---|---|
存储模型 | 全内存操作,无磁盘 IO |
数据结构 | 针对使用场景定制的轻量结构 |
执行线程 | 命令处理单线程,避免锁和上下文切换 |
网络模型 | epoll 支持海量连接 |
Key 清理策略 | 惰性 + 定期删除 + 淘汰策略,降低抖动 |
持久化 | 异步处理,避免阻塞 |
八、额外技术点
其实Redis快还得益于内存分配器:jemalloc、RESP 协议等技术,作者对这方面知识有待深入理解,后续再写文章详细描述,通常面试中回答到以上几点已经差不多可以了。
参考资料
- Redis 官方文档:https://redis.io/docs
- Redis 源码仓库:https://github.com/redis/redis
- 《Redis 设计与实现》 – 黄健宏
我是 李卷卷,专注Java相关知识输出。感谢阅读!