《Redis为什么快》
Redis 为什么快?
Redis 之所以快,主要原因可以归纳为:
内存存储 + 高效数据结构 + 单线程模型 + IO 多路复用 + 优化设计
这是 Redis 面试中非常高频的问题。
1. 基于内存存储(最核心原因)
传统数据库(例如 MySQL):
用户请求 ↓查询索引 ↓磁盘读取数据 ↓返回结果由于需要访问磁盘,速度较慢。
Redis:
用户请求 ↓内存读取 ↓返回结果数据直接存储在内存中,避免了磁盘 IO。
速度对比
| 存储方式 | 访问速度 |
|---|---|
| 磁盘 | 毫秒级 |
| 内存 | 纳秒级 |
因此 Redis 可以达到非常高的 QPS。
2. 使用高效的数据结构
Redis 并不是简单使用普通数据结构,而是针对不同场景设计了高效的数据结构。
2.1 String
Redis String 底层使用:
SDS(Simple Dynamic String)相比 C 字符串,具有以下优势:
- 记录字符串长度
- 获取长度时间复杂度 O(1)
- 避免缓冲区溢出
- 减少内存重新分配次数
例如:
SET username zhangsanGET username2.2 Hash
Hash 底层使用:
哈希表(Hash Table)查询效率:
平均时间复杂度 O(1)例如:
HSET user:1 name 张三 age 20
HGET user:1 name可以快速获取用户信息。
应用:
- 用户信息缓存
- 商品信息缓存
- 对象存储
2.3 List
List 底层使用:
quicklist结合:
链表 + 压缩结构特点:
- 插入删除速度快
- 节省内存空间
应用:
- 消息队列
- 最新消息列表
例如:
LPUSH queue taskRPOP queue2.4 Sorted Set(ZSet)
ZSet 底层结构:
跳表(SkipList)+哈希表(Hash Table)支持:
- 快速排序
- 范围查询
例如:
ZADD rank 100 user1ZADD rank 90 user2应用:
- 游戏排行榜
- 热门文章排行
- 积分排名
3. 单线程模型
Redis 6 之前,核心命令执行主要采用:
单线程处理请求执行流程:
客户端1客户端2客户端3
↓
Redis 主线程
↓
执行命令单线程为什么更快?
3.1 避免线程上下文切换
多线程:
线程A执行 ↓保存状态 ↓切换线程B ↓恢复状态线程切换会产生额外开销。
而 Redis 的命令:
GETSETINCR执行速度非常快,通常只需要微秒级。
3.2 避免锁竞争
多线程环境:
线程A | 加锁
线程B | 等待Redis 单线程:
请求1 ↓请求2 ↓请求3天然避免了很多锁竞争问题。
4. IO 多路复用
虽然 Redis 使用单线程,但是可以处理大量客户端连接。
原因:
Redis 使用:
IO 多路复用(IO Multiplexing)Linux 常见实现:
epoll传统网络模型
一个连接对应一个线程:
客户端A → 线程1
客户端B → 线程2
客户端C → 线程3缺点:
- 创建大量线程
- 消耗资源
- 上下文切换频繁
Redis 网络模型
客户端A客户端B客户端C
↓
epoll
↓
一个线程处理一个线程可以监听多个客户端连接。
5. 非阻塞 IO
Redis 使用:
非阻塞 IO不会因为某一个客户端等待数据而阻塞整个 Redis 服务。
例如:
客户端 A:
等待网络数据Redis 不会停止,而是继续处理:
客户端B客户端C提高整体吞吐量。
6. Redis 命令执行简单
Redis 的操作通常非常简单。
例如:
GET username执行流程:
计算 key 位置
↓
读取 value
↓
返回结果相比 MySQL:
SQL解析
↓
查询优化
↓
索引查找
↓
事务处理
↓
锁管理Redis 执行流程更短。
7. 高效的通信协议
Redis 使用:
RESP(Redis Serialization Protocol)特点:
- 协议简单
- 数据格式简单
- 解析速度快
- 网络开销低
因此 Redis 可以快速完成客户端通信。
8. 高效的内存管理
Redis 对内存进行了优化:
包括:
- 内存池
- 对象共享
- 压缩数据结构
例如:
Redis 会共享一些小整数对象:
0 ~ 9999减少重复创建对象造成的内存消耗。
Redis 为什么单线程还能这么快?
Redis 的瓶颈主要不是 CPU,而是网络 IO 和内存访问。Redis 使用 IO 多路复用处理大量客户端连接,同时命令执行速度非常快,因此单线程模型也可以支撑很高的吞吐量。
Redis 快主要有以下几个原因:
-
基于内存存储
数据直接存储在内存中,避免磁盘 IO。
-
高效的数据结构
使用哈希表、跳表、SDS 等优化数据结构,提高数据访问效率。
-
单线程模型
避免线程上下文切换和锁竞争。
-
IO 多路复用
一个线程可以处理大量客户端连接。
-
命令执行简单
Redis 操作流程短,没有复杂的 SQL 解析和事务处理。
-
高效通信协议
使用 RESP 协议,减少网络通信开销。
因此 Redis 可以实现高性能、高并发的数据访问。
《Redis为什么快》
作者:felinus
本文链接: https://felinus-blog.vercel.app/posts/f8882817/
本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。