Redis 完全指南 / 01 - Redis 简介
Redis 简介
1.1 什么是 Redis
Redis(Remote Dictionary Server,远程字典服务器)是一个开源的、基于内存的高性能键值对(Key-Value)数据库。它由意大利开发者 Salvatore Sanfilippo(网名 antirez)于 2009 年创建,最初是为了解决其创业公司 LLOOGG 的实时日志分析系统的性能瓶颈。
Redis 不仅仅是简单的缓存——它提供了丰富的数据结构、持久化机制、复制、集群和高可用方案,使其成为当今最流行的 NoSQL 数据库之一。
1.2 发展历史
| 时间 | 版本 | 里程碑 |
|---|---|---|
| 2009 | 1.0 | 首次开源发布,支持基本数据结构 |
| 2012 | 2.6 | Lua 脚本、毫秒级过期 |
| 2015 | 3.0 | Redis Cluster 正式发布,支持分布式集群 |
| 2018 | 5.0 | Stream 数据类型、LZF 快照压缩 |
| 2020 | 6.0 | ACL 访问控制、多线程 I/O、RESP3 协议 |
| 2022 | 7.0 | Function、Multi-Part AOF、Shared Pub/Sub |
| 2024 | 7.2 | 性能改进、向量集合(Vector Set 预览) |
💡 小知识:Redis 之名来自 “Remote Dictionary Server”,作者 antirez 最初把它当作一个更好的 Memcached。
1.3 核心特性
基于内存,极致性能
Redis 将所有数据存储在内存中(RAM),读写操作避免了磁盘 I/O 瓶颈:
| 操作 | 性能(单线程) |
|---|---|
| 读 | ~110,000 次/秒 |
| 写 | ~81,000 次/秒 |
| 延迟 | 亚毫秒级(< 1ms) |
丰富的数据结构
与 Memcached 只支持 String 不同,Redis 支持多种数据结构:
┌─────────────────────────────────────────┐
│ Redis 数据结构 │
├──────────┬──────────────────────────────┤
│ 基础类型 │ String / List / Hash │
│ │ Set / Sorted Set (ZSet) │
├──────────┼──────────────────────────────┤
│ 扩展类型 │ Bitmap / HyperLogLog │
│ │ GeoSpatial / Stream │
├──────────┼──────────────────────────────┤
│ 模块扩展 │ RedisJSON / RediSearch │
│ │ RedisGraph / RedisBloom │
└──────────┴──────────────────────────────┘
持久化支持
Redis 提供两种持久化方式,确保数据不会因为进程退出而丢失:
- RDB(Redis Database):定时快照,适合备份和灾难恢复
- AOF(Append Only File):记录每一条写操作,数据安全性更高
- 混合持久化:结合 RDB 和 AOF 的优点(Redis 4.0+)
高可用与分布式
┌──────────┐
│ Sentinel │ ← 自动故障检测与转移
│ (哨兵) │
└────┬─────┘
│
┌──────────┼──────────┐
│ │ │
┌───▼───┐ ┌───▼───┐ ┌───▼───┐
│Master │ │Slave1 │ │Slave2 │ ← 主从复制
└───────┘ └───────┘ └───────┘
┌─────┐ ┌─────┐ ┌─────┐
│Node1│ │Node2│ │Node3│ ← Redis Cluster
│slot │ │slot │ │slot │ 自动分片 + 故障转移
│0-5k│ │5k-10k│ │10k-16k│
└─────┘ └─────┘ └─────┘
其他重要特性
| 特性 | 说明 |
|---|---|
| 原子操作 | 所有操作都是原子性的,支持事务(MULTI/EXEC) |
| Pub/Sub | 内置发布订阅消息系统 |
| Lua 脚本 | 服务端执行 Lua 脚本,减少网络往返 |
| TTL | Key 支持过期时间,天然适合缓存场景 |
| Pipeline | 批量执行命令,减少网络延迟 |
| Lua 脚本 + 事务 | 实现复杂的分布式逻辑(如分布式锁) |
1.4 适用场景
✅ 非常适合的场景
| 场景 | 说明 | 使用的数据结构 |
|---|---|---|
| 缓存 | 热点数据缓存,降低数据库压力 | String / Hash |
| 会话存储(Session) | 分布式环境下的用户会话管理 | String / Hash |
| 排行榜 | 实时积分/热度排行 | Sorted Set |
| 计数器 | 页面浏览量、点赞数、库存扣减 | String(INCR) |
| 分布式锁 | 分布式环境下的资源互斥 | String(SET NX) |
| 消息队列 | 轻量级异步任务队列 | List / Stream |
| 社交关系 | 关注/粉丝/共同好友 | Set(交集/差集) |
| 实时分析 | UV 统计、在线用户数 | HyperLogLog / Bitmap |
| 地理位置 | 附近的人/商家 | GeoSpatial |
| 限流/防刷 | API 限流、短信防刷 | String + 过期时间 |
⚠️ 不太适合的场景
| 场景 | 原因 | 替代方案 |
|---|---|---|
| 海量数据持久存储 | 内存成本高,数据量受限于 RAM | MySQL / PostgreSQL / MongoDB |
| 复杂查询 | 不支持 SQL、JOIN、聚合 | Elasticsearch / ClickHouse |
| 大量文本搜索 | 全文检索能力有限 | Elasticsearch / Meilisearch |
| 二进制大对象存储 | Value 过大影响性能 | MinIO / OSS / S3 |
| 强事务(ACID) | 仅支持弱事务 | MySQL / PostgreSQL |
1.5 Redis vs Memcached 全面对比
这是技术选型中最常被问到的问题。两者都是基于内存的键值存储,但设计理念和功能差异显著:
| 对比维度 | Redis | Memcached |
|---|---|---|
| 数据结构 | String, List, Hash, Set, ZSet, Stream, Bitmap, HyperLogLog, Geo | 仅 String(Key-Value) |
| 持久化 | ✅ 支持 RDB + AOF | ❌ 不支持,重启数据丢失 |
| 集群模式 | ✅ Redis Cluster(官方) | 客户端一致性哈希 |
| 高可用 | ✅ Sentinel + 主从复制 | ❌ 无原生高可用方案 |
| 发布订阅 | ✅ Pub/Sub + Stream | ❌ 不支持 |
| Lua 脚本 | ✅ 服务端执行 | ❌ 不支持 |
| 过期策略 | 惰性删除 + 定期删除 | 惰性删除(LRU) |
| 内存效率 | 略高(有额外结构开销) | 更高(slab 分配器) |
| 线程模型 | 单线程(6.0+ 多线程 I/O) | 多线程 |
| 最大 Value | 512 MB | 1 MB(默认) |
| 协议 | RESP(二进制安全) | 文本/二进制协议 |
| 事务 | ✅ MULTI/EXEC(弱事务) | ❌ 仅 CAS(乐观锁) |
| 社区活跃度 | 非常活跃 | 相对缓慢 |
选型建议
需要复杂数据结构? ──是──→ Redis
│
否
│
需要持久化? ──是──→ Redis
│
否
│
需要高可用/集群? ──是──→ Redis
│
否
│
纯粹简单 KV 缓存 + 多线程并发? ──是──→ Memcached
│
否
│
Redis(默认选择)
💡 结论:对于绝大多数新项目,Redis 是更优选择。除非你的场景是纯缓存、对内存效率极度敏感且不需要持久化,否则 Memcached 的优势很小。
1.6 Redis 与数据库的协作模式
在实际项目中,Redis 通常不作为唯一的数据库,而是与关系型数据库配合使用:
┌──────────┐ ① 先查 Redis ┌──────────┐
│ │ ─────────────────→ │ │
│ Client │ 命中则直接返回 │ Redis │
│ │ │ (Cache) │
│ │ ② 未命中查 DB │ │
│ │ ─────────────────→ └──────────┘
│ │ ┌──────────┐
│ │ ③ 写回 Redis │ │
│ │ ←───────────────── │ Database │
└──────────┘ │ (MySQL) │
└──────────┘
Cache Aside Pattern(旁路缓存)
def get_user(user_id):
# 1. 先查缓存
cache_key = f"user:{user_id}"
cached = redis.get(cache_key)
if cached:
return json.loads(cached)
# 2. 缓存未命中,查数据库
user = db.query("SELECT * FROM users WHERE id = %s", user_id)
if user:
# 3. 写入缓存,设置 TTL
redis.setex(cache_key, 3600, json.dumps(user))
return user
⚠️ 注意:写数据库后要删除缓存(而非更新缓存),避免并发导致缓存与数据库不一致。
1.7 Redis 版本选择建议
| 场景 | 推荐版本 | 理由 |
|---|---|---|
| 新项目 | Redis 7.2+ | 最新特性、性能优化、安全性 |
| 已有项目升级 | Redis 7.0+ | Multi-Part AOF、Function |
| 只需要缓存 | Redis 6.0+ | ACL、多线程 I/O |
| 企业级需求 | Redis Stack 7.2+ | JSON、Search、Graph 一体化 |
1.8 快速体验
最快的体验方式是使用 Docker(下一章会详细介绍安装):
# 一行命令启动 Redis
docker run -d --name redis-quick -p 6379:6379 redis:7.2
# 连接并测试
docker exec -it redis-quick redis-cli
# 在 redis-cli 中尝试
127.0.0.1:6379> SET hello "Hello Redis!"
OK
127.0.0.1:6379> GET hello
"Hello Redis!"
127.0.0.1:6379> LPUSH languages "Python" "Go" "Rust"
(integer) 3
127.0.0.1:6379> LRANGE languages 0 -1
1) "Rust"
2) "Go"
3) "Python"
127.0.0.1:6379> ZADD leaderboard 100 "Alice" 85 "Bob" 92 "Charlie"
(integer) 3
127.0.0.1:6379> ZREVRANGE leaderboard 0 -1 WITHSCORES
1) "Alice"
2) "100"
3) "Charlie"
4) "92"
5) "Bob"
6) "85"
📌 业务场景
场景一:电商商品缓存
电商平台中,商品详情页的 QPS 可能达到数万。直接查询 MySQL 会导致数据库过载。使用 Redis 缓存热门商品,TTL 设置为 10-30 分钟,可以将数据库压力降低 90% 以上。
场景二:社交平台计数
微博/Twitter 类平台需要实时显示点赞数、评论数、转发数。使用 Redis 的 INCR/DECR 命令,可以在 O(1) 时间内完成计数更新,避免高并发下的数据库行锁竞争。
场景三:游戏排行榜
手游中的实时排行榜需要频繁更新分数并查询 Top N。Redis 的 Sorted Set 天然支持按分数排序,ZADD O(log N) 更新,ZREVRANGE O(log N + M) 查询,完美匹配排行榜需求。