Redis 为什么这么快?
date
Feb 10, 2025
slug
why-redis-so-fast
status
Published
tags
Tips
Redis
Network
summary
type
Post
Created Time
Feb 10, 2025 01:23 PM
Updated Time
Feb 10, 2025 02:33 PM
AI summary
Status
Redis 作为一款高性能的内存数据库,以其卓越的速度和低延迟著称。那么,Redis 为什么这么快?本文将从多个维度深入剖析 Redis 的高性能原因。
1、纯内存存储
Redis 的所有读写操作都是在内存中完成的,相比传统基于磁盘的数据库(如 MySQL),内存的读写速度要快几个数量级。由于数据直接从内存读取,避免了磁盘 I/O 的瓶颈,从而实现了微秒级别的响应时间。
2、单线程架构 + I/O 多路复用
Redis 的单线程模型,指的是它的它的 主线程 处理所有的 客户端请求,包括读写操作、键值存取、数据结构操作等。这种模型有两个优点:
- 不需要用锁来防止数据竞争;
- 避免了线程切换带来的 CPU 消耗;
但同时,也有三个缺点:
- 无法利用多核 CPU,即使你的 CPU 有 8 个核,单线程 Redis 只能用到其中 一个核心,这可能会成为性能瓶颈。
- CPU 密集型的任务,如
KEYS
、FLUSHALL
、SORT
这些可能会大量数据的操作,会阻塞 Redis 的主线程,导致其他请求被延迟处理。
- 性能依赖网络 I/O,如果单个实例的网络吞吐量不足,可能会成为瓶颈。
为了解决单线程带来的性能瓶颈问题,Redis 采用了 I/O 多路复用(多个 socket 共同使用一个线程),同时监听多个 socket 连接,将 epoll 中的各种事件分派到不同的事件处理器中执行,避免了在 I/O 上浪费时间。
Redis 6.0 及以后 引入了 多线程 I/O 处理,但仍然保持单线程执行命令。这个优化减少了 网络 I/O 的瓶颈,提升了高并发场景下的吞吐量。
3、高效的数据结构
Redis 的数据结构为了在性能和内存之间取得平衡,有的数据类型底层使用了不止一种数据结构:
- String(字符串)
- 使用 SDS 来管理字符串,支持动态扩容。
strlen()
操作的事件复杂度为 O(1)。- 对于短字符串(小于 39 字节),采用
embstr
结构,将 SDS 直接存储在 Redis 对象结构体中,减少内存碎片,提高访问效率。 - 对于长字符串(大于等于 39 字节)。采用
raw
结构,SDS 存储在堆上,提高扩展性。
- List(列表)
- 小列表:使用 ZipList(压缩列表),减少内存开销。
- 大列表:使用 QuickList,多个
ziplist
组成 双向链表,既节省内存,又保证了 O(1) 级别的插入和删除效率。
- Hash(哈希)
- 小哈希(字段数量 ≤ 512 个 且 总长度 ≤ 64 KB)采用 ZipList(压缩列表),采用连续内存存储,查询效率为 O(N)。
- 大哈希采用 HashTable(字典),通过 链地址法(拉链法) 解决哈希冲突,查询效率为 O(1)。
- Set(集合)
- 小集合(元素全是整数,且数量较少 ≤ 512 个):使用 IntSet(整数集合)数据结构,采用 连续数组存储,提高访问速度,并自动扩容,查询复杂度为 O(log N)(二分查找)。
- 大集合:采用 HashTable(字典) 存储,查询、插入 O(1),但占用更多内存。
- Zset(有序集合)
- 小数据量(元素 ≤ 128 个,且总长度 ≤ 64 KB):使用 ZipList(压缩列表)数据结构,顺序存储,节省内存,但复杂度查询较慢,为
O(N)
。 - 大数据量:使用 SkipList(跳表)+ HashTable,跳表(SkipList)实现 O(log N) 排序查询,HashTable 用于 O(1) 查找分值。
4、高效的序列化协议(RESP)
Redis 使用 RESP(Redis Serialization Protocol) 进行数据通信,该协议具有以下特点:
- 简单易解析(基于文本,但比 JSON/ XML 更高效)。
- 高效(低解析开销,可直接用
read
/write
解析)。 - 直接按 前缀字符(
+
、、
:
、$
、)判断数据类型,无需复杂解析逻辑。
- 服务器可以用 一次
read()
读取完整命令,减少系统调用次数,提高性能。
- 支持多种数据类型(字符串、整数、数组、错误等)。
- 支持流水线(Pipelining)(减少网络延迟,提高吞吐量)。
5、高效的网络模型
Redis 使用 基于事件驱动的网络模型,结合 epoll 进行高效的 I/O 处理。同时,Redis 支持 Pipeline 机制,允许客户端批量发送命令,从而减少网络往返(RTT)时间。
总结
Redis 为了“快”,在多方面做了优化,正是这些核心优化,使得 Redis 能够在高并发环境下提供卓越的性能,成为缓存、消息队列、排行榜等场景的首选方案。