Redis 为什么这么快?—— 8 个维度彻底讲透高性能缓存原理》
一、开篇一个面试题引发的思考面试官Redis 为什么这么快我因为它是基于内存的。面试官还有呢我……嗯它用的 IO 多路复用面试官还有呢—— 这个场景是不是很熟悉很多人对 Redis 快的原因理解停留在「内存数据库」这四个字上。但内存数据库不止 Redis 一个为什么 Redis 能杀出重围今天我们从 8 个维度 彻底讲清楚这件事。二、维度一纯内存操作这是最直观的原因。传统数据库如 MySQL为了持久化数据存储在磁盘上每次读写都要经过磁盘 IO。而 Redis 的数据全部放在内存里读写速度比磁盘快几个数量级。内存读取 ≈ 0.1μs磁盘读取 ≈ 10ms相差 10 万倍三、维度二高效的数据结构Redis 不是简单的 key-value 存储它为每种数据类型精心设计了底层数据结构数据类型 底层实现 优势String SDS简单动态字符串 O(1) 获取长度预分配空间避免频繁扩容Hash ZipList / HashTable 小数据量用压缩列表大数据量用哈希表List QuickList 双向链表 压缩列表的组合Set IntSet / HashTable 整数集合自动升级ZSet SkipList HashTable 跳表实现 O(logN) 的插入和查询特别提一下 SDS它相比 C 语言的字符串多了 len 字段可以直接 O(1) 获取字符串长度而且通过预分配空间减少内存重分配次数。四、维度三IO 多路复用Redis 使用 单线程 IO 多路复用 的模型。很多人问单线程怎么处理高并发答案是Redis 的瓶颈不在 CPU而在 IO。epollLinux把网络 IO 事件注册到内核内核监听这些事件有数据到达时通知 Redis单线程避免了锁竞争、上下文切换的开销单线程在 Redis 这个场景下反而是优势。五、维度四避免上下文切换传统多线程应用频繁在用户态和内核态之间切换每次切换都有开销。Redis 单线程模型基本没有上下文切换CPU 时间全部用于处理命令。六、维度五渐进式 rehash当哈希表的数据量增长时Redis 需要扩容。如果一次性迁移所有数据会阻塞整个服务。Redis 的解决方案渐进式 rehash。同时维护两个哈希表每次操作时顺带迁移一个桶将扩容的耗时分摊到每一次操作中七、维度六合理的过期策略Redis 的过期键清理策略是 惰性删除 定期删除 的组合惰性删除访问 key 时检查是否过期过期则删除定期删除每秒执行 10 次每次检查一定数量的过期 key这种策略在保证时效性的同时避免了大量过期 key 同时删除导致的卡顿。八、维度七事件驱动模型Redis 自己实现了一套事件驱动库 ae把文件事件socket 读写和时间事件定时任务统一处理。核心流程注册事件回调获取就绪的事件按优先级处理九、维度八管道与批量操作了解 Redis 的人都知道使用 pipeline 可以大幅提升性能普通模式N 次命令 N 次网络往返PipelineN 次命令 1 次网络往返加上 MSET、HMGET 等批量命令Redis 进一步减少了网络开销。十、总结维度 一句话内存 数据在内存读写快数据结构 为场景优化内存紧凑IO 模型 epoll 多路复用线程模型 单线程无锁竞争rehash 渐进式不阻塞过期策略 惰性 定期事件驱动 自研 ae 库批量操作 pipeline 批量命令最后留一个问题 Redis 单线程模型有没有缺点什么情况下 Redis 会变慢欢迎在评论区留言讨论