第一章 Redis 是什么
1.1 一句话理解 Redis
Redis(Remote Dictionary Server)= 一个运行在内存中的键值数据库。
你可以把它想象成一个超大的 HashMap,数据存在内存里,所以读写速度极快——单机每秒可以处理 10 万+ 次读写操作。
┌─────────────────────────────────────┐
│ Redis │
│ │
│ Key (字符串) ──→ Value (多种类型) │
│ │
│ "user:1001" ──→ "张三" │
│ "order:count"──→ 8527 │
│ "rank:game" ──→ [有序集合] │
│ │
└─────────────────────────────────────┘核心特点一句话总结:
| 特点 | 说明 |
|---|---|
| 基于内存 | 数据主要存储在内存中,读写极快 |
| 键值模型 | 所有数据都是 Key → Value 的映射 |
| 数据类型丰富 | Value 不只是字符串,还支持列表、哈希、集合等 |
| 支持持久化 | 虽然在内存中,但可以把数据保存到磁盘,重启不丢失 |
| 单线程模型 | 命令执行是单线程的,天然避免了并发竞争问题 |
1.2 Redis 能解决什么问题
Redis 不是万能的,但在以下场景中它是最佳选择:
场景一:缓存加速
这是 Redis 最常见的用途。把数据库查询结果缓存到 Redis,下次直接从内存读取,响应时间从几十毫秒降到亚毫秒级。
用户请求 → 先查 Redis(命中?直接返回)
↓ 未命中
查 MySQL → 写入 Redis → 返回场景二:会话管理(Session)
Web 应用中,用户登录后的 Session 信息存到 Redis,多个应用服务器可以共享同一份 Session,轻松实现分布式会话。
场景三:排行榜
利用 Redis 的有序集合(Sorted Set),天然支持按分数排名,实现游戏排行榜、热搜榜等功能只需要几行命令。
场景四:计数器
文章阅读量、点赞数、接口调用次数……Redis 的 INCR 命令是原子操作,高并发下也不会出错。
场景五:消息队列
利用 List 或 Stream 类型,Redis 可以充当轻量级消息队列,适合对可靠性要求不是极高的异步任务场景。
场景六:分布式锁
多个服务需要抢占同一个资源时,Redis 的 SETNX 命令可以实现简单高效的分布式锁。
一句话概括:凡是需要 "高速读写" 或 "多服务共享数据" 的场景,都可以考虑 Redis。
1.3 Redis vs MySQL —— 什么时候该用 Redis
很多初学者会问:有了 MySQL 为什么还要 Redis?它们不是竞争关系,而是互补关系。
| 对比维度 | MySQL | Redis |
|---|---|---|
| 存储位置 | 磁盘 | 内存(可持久化到磁盘) |
| 速度 | 毫秒级 | 微秒 ~ 亚毫秒级 |
| 数据模型 | 关系表(行和列) | 键值对(Key-Value) |
| 数据容量 | 可以存储 TB 级数据 | 受内存大小限制,通常 GB 级 |
| 查询能力 | 支持复杂 SQL 查询 | 只支持按 Key 查找,无 JOIN |
| 事务 | 完整 ACID 事务 | 简单事务,不支持回滚 |
| 典型角色 | 主数据库,数据持久存储 | 辅助层,加速 & 共享 |
选择原则
问自己两个问题:
1. 这个数据需要复杂查询(JOIN、GROUP BY)吗?
→ 是:用 MySQL
→ 否:继续看第二个问题
2. 这个数据需要高频读写、或者多服务共享?
→ 是:用 Redis(或 Redis + MySQL 配合)
→ 否:MySQL 就够了实际项目中最常见的架构:MySQL 做主存储,Redis 做缓存层,两者配合使用。
┌────────┐ ┌────────┐ ┌────────┐
│ 客户端 │────→│ Redis │────→│ MySQL │
│ │←────│ (缓存层) │←────│ (主存储) │
└────────┘ └────────┘ └────────┘
读请求:客户端 → Redis(命中直接返回)→ 未命中则查 MySQL → 回写 Redis
写请求:客户端 → MySQL(写主库)→ 更新/删除 Redis 缓存1.4 Redis 的整体架构概览
在深入学习之前,先建立一个对 Redis 内部架构的整体认知。
单线程模型
Redis 的命令执行是单线程的。你可能会问:单线程怎么能这么快?
原因有三:
- 纯内存操作:内存读写本身就是纳秒级的
- I/O 多路复用:用一个线程同时监听成千上万个连接(epoll / kqueue)
- 避免上下文切换:不需要加锁,没有线程切换的开销
多个客户端连接
┌──── Client A
│──── Client B
│──── Client C
↓
┌─────────────────┐
│ I/O 多路复用器 │ ← 一个线程监听所有连接
│ (epoll/kqueue) │
└───────┬─────────┘
↓
┌─────────────────┐
│ 命令执行(单线程) │ ← 逐个执行命令,无需加锁
└───────┬─────────┘
↓
┌─────────────────┐
│ 内存数据存储 │
└─────────────────┘注意:Redis 6.0 之后引入了多线程 I/O,但仅用于网络数据的读写,命令执行仍然是单线程的。所以说"Redis 是单线程"这个说法在核心逻辑上依然成立。
内存 + 持久化
Redis 的数据存在内存中,但提供了两种持久化机制防止数据丢失:
┌──────────────┐
│ 内存数据 │
│ (主战场) │
└──────┬───────┘
│
├──→ RDB 快照:定时把内存数据"拍一张照片"保存到磁盘
│
└──→ AOF 日志:把每条写命令追加记录到日志文件这两种机制会在后续章节详细展开,现在只需要知道:Redis 虽然是内存数据库,但数据是可以持久化的,不会因为重启就全部丢失。
Redis 完整架构一图流
┌─────────────────────────────────────────────────────┐
│ Redis Server │
│ │
│ ┌──────────┐ ┌──────────────┐ ┌─────────────┐ │
│ │ 网络层 │ │ 命令处理器 │ │ 数据存储 │ │
│ │ I/O多路复用│──→│ 单线程执行 │──→│ 内存数据库 │ │
│ └──────────┘ └──────────────┘ └──────┬──────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ 持久化 │ │
│ │ RDB / AOF │ │
│ └─────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │
│ │ 事务 │ │ Lua脚本 │ │ 发布/订阅 │ │
│ └──────────┘ └──────────┘ └────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │
│ │ 主从复制 │ │ 哨兵模式 │ │ 集群模式 │ │
│ └──────────┘ └──────────┘ └────────────────┘ │
└─────────────────────────────────────────────────────┘本章小结
| 知识点 | 要点 |
|---|---|
| Redis 本质 | 基于内存的键值数据库,读写极快 |
| 核心场景 | 缓存、会话、排行榜、计数器、消息队列、分布式锁 |
| 与 MySQL 的关系 | 互补而非替代,通常 MySQL 做主存储 + Redis 做缓存 |
| 单线程为什么快 | 纯内存 + I/O 多路复用 + 无锁无切换 |
| 数据安全 | 支持 RDB 快照和 AOF 日志两种持久化方式 |
下一章预告:动手把 Redis 跑起来——安装、启动、用 redis-cli 执行你的第一条命令。