Redis介绍
1. 核心特性
- 内存存储:数据主要保存在内存中,读写速度极快(微秒级响应)。
- 持久化支持:可通过 RDB(快照)和 AOF(追加日志)机制将数据持久化到磁盘。
- 丰富的数据结构 :不仅支持字符串(String),还支持:
- 列表(List)
- 集合(Set)
- 有序集合(Sorted Set / ZSet)
- 哈希(Hash)
- 位图(Bitmap)、超日志(HyperLogLog)、地理空间(Geo)等
- 高可用与扩展性 :
- 主从复制(Replication)
- 哨兵模式(Sentinel)实现自动故障转移
- Redis Cluster 支持分布式部署和自动分片
2. 典型应用场景
- 缓存:减轻数据库压力,加速热点数据访问。
- 会话存储:如用户登录状态、购物车信息。
- 排行榜/计数器:利用 Sorted Set 实现。
- 消息队列:通过 List 或 Stream 实现轻量级队列。
- 分布式锁 :使用
SET key value NX EX实现。 - 实时统计:如 UV/PV 统计(HyperLogLog)、在线用户数(Set)。
3. 关键命令示例
bash
# 字符串
SET user:1001 "Alice"
GET user:1001
# 哈希
HSET user:1001 name "Alice" age 30
HGET user:1001 name
# 列表(左进右出)
LPUSH tasks "task1"
RPOP tasks
# 有序集合(带分数排序)
ZADD leaderboard 100 "player1"
ZREVRANGE leaderboard 0 9 WITHSCORES # 获取前10名
# 设置过期时间
EXPIRE session:abc123 1800 # 30分钟过期
4. 性能与优化
- 避免大 Key:单个 Value 过大会阻塞主线程。
- 合理设置过期时间:防止内存无限增长。
- 使用 Pipeline:批量发送命令减少网络往返。
- 监控内存使用 :通过
INFO memory查看。 - 选择合适的数据结构:例如用 Hash 存储对象比多个 String 更省内存。
5. 安全与运维
- 绑定 IP 和设置密码 (
requirepass)。 - 禁用危险命令 (如
FLUSHALL,KEYS *)通过rename-command。 - 定期备份 RDB/AOF 文件。
- 监控工具 :Redis 自带
redis-cli --stat,或使用 Prometheus + Grafana。
6. 高级功能(Redis 6+)
- ACL(访问控制列表):精细化权限管理。
- Redis Streams:更强大的消息队列,支持消费者组。
- 多线程 I/O(Redis 6+):提升网络读写性能(但命令执行仍是单线程)。
- Redis Functions(Redis 7+):类似 Lua 脚本但更安全高效。
Redis 为什么这么快?
Redis 被广泛用作高性能缓存和实时数据存储系统,其"快"并非偶然,而是由多个关键设计决定的:
1. 基于内存操作
Redis 将所有数据存储在内存中,避免了磁盘 I/O 的延迟。内存访问速度通常在纳秒级,而传统磁盘(即使是 SSD)也在微秒到毫秒级,差距可达千倍以上。
2. 单线程模型 + I/O 多路复用
- Redis 核心命令处理采用单线程(6.0 之前完全单线程,6.0+ 网络 I/O 多线程,命令执行仍单线。
- 利用 epoll/kqueue 等 I/O 多路复用技术,一个线程可高效处理成千上万个并发连接,避免了线程切换和锁竞争的开销。
- 单线程也意味着无需复杂的并发控制,逻辑简单且稳定。
3. 高效的数据结构
Redis 不仅是简单的 key-value 存储,它为不同场景提供了高度优化的底层数据结构:
- 字符串(SDS:Simple Dynamic String)
- 哈希表(渐进式 rehash 避免阻塞)
- 跳表(用于 Sorted Set,支持 O(log N) 插入/查询)
- 压缩列表(ziplist)、整数集合(intset)等内存紧凑结构
这些结构在时间和空间上都做了极致优化。
4. 避免上下文切换与锁竞争
由于核心逻辑单线程执行,Redis 几乎不需要加锁,极大减少了 CPU 在调度和同步上的浪费。
💡 总结:内存存储 + 单线程事件驱动 + 精巧数据结构 = 极致性能
Redis 集群架构演进:从主从复制到 Redis Cluster
随着业务规模的增长,Redis 的部署架构也经历了清晰的演进路径:主从复制 → 哨兵模式 → Redis Cluster。每一步都是为了解决前一阶段无法克服的瓶颈。
1. 主从复制(Replication)------解决单点故障,但能力有限
- 核心机制:一个主节点(Master)负责读写,多个从节点(Slave/Replica)异步复制主节点数据,提供只读服务。
- 优点 :
- 数据冗余,避免单点宕机导致服务完全中断;
- 可分担读请求压力(读写分离)。
- 致命缺陷 :
- 写操作仍集中在单个主节点,无法水平扩展写吞吐;
- 所有节点存储全量数据,内存容量受限于单机上限;
- 故障切换需人工干预,不具备自动恢复能力。
✅ 适用场景:小规模、对高可用要求不高、读多写少的系统。
2. 哨兵模式(Sentinel)------实现自动故障转移
- 在主从基础上引入 Sentinel 集群(通常 3 节点以上),用于监控主从状态。
- 核心功能 :
- 监控(Monitoring):持续检查主从节点健康状态;
- 自动故障转移(Failover):主节点宕机后,自动选举一个从节点晋升为主;
- 通知(Notification):可触发告警或回调;
- 配置提供者(Configuration Provider):客户端通过 Sentinel 获取当前主节点地址。
- 改进点 :
- 实现了 高可用自动化,减少运维负担。
- 仍未解决的问题 :
- 数据仍全量复制,无法突破单机内存限制;
- 写性能无法横向扩展,依然是"单写多读"架构。
⚠️ 哨兵只是"高可用方案",不是"分布式方案"。
3. Redis Cluster ------ 真正的分布式解决方案
Redis 3.0(2015年)正式引入 Cluster 模式,标志着 Redis 迈入原生分布式时代。
核心设计思想:分片 + 去中心化 + 自动故障恢复
| 特性 | 说明 |
|---|---|
| 数据分片(Sharding) | 将 key 空间划分为 16384 个槽(slot),每个主节点负责一部分槽。 |
| 无中心架构 | 所有节点对等通信,通过 Gossip 协议交换集群状态,无需哨兵或代理。 |
| 读写均可扩展 | 增加主节点即可提升存储容量和写吞吐;每个主可挂从节点提升读能力。 |
| 自动故障转移 | 主节点宕机后,其从节点自动选举晋升,全程无需外部干预。 |
| 客户端智能路由 | 客户端缓存 slot 到节点的映射,直接连接目标节点(支持 -MOVED 重定向)。 |
✅ 解决了什么?
- 容量瓶颈:数据分散在多个节点,总内存 = 各节点之和;
- 性能瓶颈:写请求可并行处理;
- 运维复杂度:内置高可用,无需额外部署哨兵。
🌟 Cluster = 高可用 + 水平扩展 + 自治
Redis 缓存失效策略:过期 + 淘汰双保险
在高并发系统中,Redis 作为缓存层,不仅要"快",还要"智能"地管理数据生命周期。否则,要么缓存长期不更新导致数据陈旧,要么内存爆满引发服务崩溃。为此,Redis 提供了两套互补的失效机制:
✅ 过期策略(Expiration Policy) :控制"单个 key 何时失效"
✅ 内存淘汰策略(Eviction Policy):控制"内存不足时删哪些 key"
一、过期策略:让缓存自动"过期"
1. 如何设置过期时间?
bash
# 设置 key 的生存时间(TTL)
SET user:1001 "Alice" EX 3600 # 1 小时后过期
EXPIRE session:abc 1800 # 给已有 key 设置 30 分钟过期
SETEX token:xyz 600 "abc123" # 原子操作:设值 + 设过期
2. Redis 如何删除过期 key?------惰性删除 + 定期删除
Redis 并不会在 key 到期瞬间立即删除它,而是采用 组合策略 平衡性能与内存:
| 策略 | 说明 | 优点 | 缺点 |
|---|---|---|---|
| 惰性删除(Lazy Expiration) | 只有当客户端访问某个 key 时,才检查是否过期,若过期则删除 | CPU 友好,不浪费计算资源 | 过期 key 可能长期驻留内存 |
| 定期删除(Periodic Expiration) | Redis 每秒运行 10 次(可配置),随机抽样部分设置了过期的 key,删除其中已过期的 | 主动释放内存,避免大量过期 key 积压 | 增加 CPU 开销 |
🔍 实际效果:既不会频繁扫描全量 key,也不会让过期数据无限堆积。
二、内存淘汰策略:当 Redis "装不下" 时怎么办?
即使设置了过期时间,如果写入速度远大于过期/删除速度,或存在大量永不过期的 key,Redis 仍可能耗尽内存。此时,就需要 内存淘汰策略(maxmemory-policy) 来兜底。
1. 开启内存限制
在 redis.conf 中配置:
conf
maxmemory 4gb # 最大使用 4GB 内存
maxmemory-policy allkeys-lru # 指定淘汰策略
2. 八种淘汰策略详解
| 策略 | 适用场景 | 行为说明 |
|---|---|---|
| noeviction(默认) | 不希望丢失任何数据 | 内存满后拒绝写入,返回错误(OOM) |
| allkeys-lru | 通用推荐 | 从所有 key 中淘汰最近最少使用(LRU)的 key |
| volatile-lru | 所有 key 都设置了过期时间 | 仅从有过期时间的 key中按 LRU 淘汰 |
| allkeys-lfu(Redis 4.0+) | 热点数据明显 | 淘汰最不经常使用(LFU)的 key(比 LRU 更精准) |
| volatile-lfu | 同上,但只针对带过期的 key | 仅淘汰带过期时间的 LFU key |
| allkeys-random | 数据访问完全随机 | 随机淘汰任意 key |
| volatile-random | 测试或特殊场景 | 随机淘汰带过期时间的 key |
| volatile-ttl | 希望优先淘汰"快过期"的数据 | 优先淘汰剩余存活时间(TTL)最短的 key |
💡 最佳实践建议:
- 如果 Redis 纯做缓存 (所有数据可重建)→ 用
allkeys-lru或allkeys-lfu- 如果 Redis 混合存储 (部分 key 永久,部分缓存)→ 用
volatile-lru,并确保缓存 key 都设了过期时间- 生产环境切勿使用
noeviction,除非你明确接受写失败
三、常见陷阱与优化建议
-
"缓存雪崩" :大量 key 同时过期 → 数据库瞬时压力暴增
✅ 解决方案:给过期时间加随机偏移(如
EX 3600 ± 300) -
"缓存穿透" :查询不存在的数据,绕过缓存直击 DB
✅ 解决方案:对空结果也缓存(如
SET null_key "" EX 60),或用布隆过滤器 -
永不过期的 key 占满内存
✅ 解决方案:定期审计 key,或强制使用
volatile-*策略 + 规范开发流程 -
LRU/LFU 精度问题
✅ Redis 使用近似算法 (采样 LRU/LFU),可通过
maxmemory-samples调整精度(默认 5)
学习资源推荐
- 官方文档:https://redis.io/documentation
- 书籍:《Redis设计与实现》(黄健宏)
- 在线练习:https://try.redis.io/
- 可视化工具:RedisInsight、Another Redis Desktop Manager
本文最终由AI生成,感谢!