目录
一、Redis 的核心特点
二、Redis 常见数据类型
三、持久化机制
1、RDB(Redis Database)
核心原理
优缺点
配置参数(redis.conf)
适用场景
2、AOF(Append Only File)
核心原理
优缺点
配置参数(redis.conf)
数据恢复流程
3、混合持久化(Hybrid Persistence)
核心原理
配置方式
4、两种持久化机制对比
四、Redis的过期键的删除策略
1、惰性删除
2、定期删除
3、内存淘汰机制
五、redis事务
1、事务相关命令
2、事务执行流程
3、事务的特性(与传统数据库的对比)
六、集群方案
1、主从复制(Master-Slave Replication)
1. 架构特点
2. 核心功能
3. 优缺点
4. 适用场景
2、哨兵模式(Sentinel)
1. 架构特点
2. 核心流程
3. 优缺点
4. 适用场景
3、集群模式(Cluster)
1. 架构特点(Redis Cluster)
2. 核心机制
3. 优缺点
4. 适用场景
4、三种模式对比表格
5、选择建议
七、redis缓存三兄弟
1、缓存穿透
问题描述
成因
解决方案
2、缓存击穿
问题描述
成因
解决方案
3、缓存雪崩
问题描述
成因
解决方案
4. 三兄弟对比总结
Redis(Remote Dictionary Server) 是一款基于内存的高性能键值对存储数据库,同时也是一个 数据结构服务器。它支持多种复杂的数据结构,并提供高读写性能、持久化、集群、事务等功能,被广泛应用于缓存、实时数据处理、消息队列、计数器、排行榜等场景。
基于内存(In-Memory)
丰富的数据结构
Redis 支持多种数据结构,每种结构对应不同的应用场景:
user:1 {name: "Alice", age: 25}
)。持久化机制
单线程与高性能
原生支持集群(Cluster)
其他功能
数据类型 | 特点 | 典型命令 | 应用场景 | 底层实现 | 内存优化建议 |
---|---|---|---|---|---|
字符串 (String) |
- 最基础类型 - 二进制安全(可存储图片、JSON 等) - 最大支持 512MB |
SET key value GET key INCR key MSET k1 v1 k2 v2 |
- 缓存(如用户信息) - 计数器(点赞数、访问量) - 分布式锁( SETNX ) |
- 短字符串:embstr 编码(一次内存分配) - 长字符串:raw 编码(两次内存分配) |
- 避免大字符串(>10KB) - 批量操作使用 MSET /MGET |
哈希 (Hash) |
- 键值对集合(field→value) - 类似 Java 的 HashMap |
HSET hash field value HGET hash field HGETALL hash HINCRBY |
- 存储对象(如用户详情) - 存储配置项(如应用配置) |
- 小哈希:压缩列表(ziplist) - 大哈希:哈希表(hashtable) |
- 控制元素数量(默认 < 512) - 值长度 < 64 字节(触发压缩列表) |
列表 (List) |
- 有序可重复 - 支持双向插入 / 删除 - 底层为双向链表 |
LPUSH list value1 value2 RPOP list LRANGE list 0 -1 BLPOP |
- 消息队列(FIFO/LIFO) - 最新动态列表(如微博时间线) |
- 小列表:压缩列表(ziplist) - 大列表:快速列表(quicklist) |
- 避免一次性获取全量数据(LRANGE 0 -1 )- 使用 BLPOP 实现阻塞队列 |
集合 (Set) |
- 无序唯一 - 支持交集 / 并集 / 差集运算 |
SADD set member1 member2 SMEMBERS set SINTER set1 set2 SCARD |
- 去重(如用户标签) - 社交关系(共同好友) - 抽奖系统(随机取元素) |
- 整数集合(intset):全整数元素 - 哈希表(hashtable):含字符串元素 |
- 控制元素数量(>512 自动转为哈希表) - 批量操作使用 SUNIONSTORE |
有序集合 (Sorted Set) |
- 每个元素关联分数(score) - 按分数排序(支持范围查询) |
ZADD zset score1 member1 score2 member2 ZRANGE zset 0 -1 WITHSCORES ZINCRBY |
- 排行榜(如游戏积分) - 时间线(按时间戳排序) - 带权重的任务调度 |
- 跳表(skiplist)+ 哈希表 - 小数据:压缩列表(ziplist) |
- 避免大范围查询(ZRANGE 参数过大)- 定期清理过期数据 |
位图 (Bitmap) |
- 基于位操作的字符串 - 每个位存储 0/1 |
SETBIT key offset value GETBIT key offset BITCOUNT key |
- 签到统计(每日 1 位) - 用户活跃状态(亿级用户仅需 12.5MB) - 布隆过滤器 |
- 基于字符串实现(本质是二进制数组) | - 按位操作,避免整键读取 - 大位图可分段存储 |
补充说明
数据类型选择原则
内存优化关键
MSET
/MGET
、HMSET
/HMGET
减少网络开销。EXPIRE
时间,避免冷数据长期占用内存。性能注意事项
KEYS *
、LRANGE list 0 -1
、SMEMBERS
,可能阻塞主线程,生产环境慎用。底层编码转换
Redis 会根据数据量和类型自动转换编码(如小哈希从 ziplist 转为 hashtable),可通过OBJECT ENCODING key
查看。
Redis 提供了两种持久化机制:RDB(快照持久化) 和 AOF(日志追加持久化),用于将内存中的数据持久化到磁盘,避免因进程退出或服务器宕机导致数据丢失。此外,Redis 4.0 引入了 混合持久化 模式,结合两者优势。以下是详细解析:
.rdb
文件。redis.conf
中的配置规则(如 save 900 1
表示 900 秒内至少 1 次写操作则触发)。SAVE
:阻塞主线程,直到快照完成(生产环境慎用)。BGSAVE
:fork 子进程执行快照,主线程继续处理请求(推荐方式)。.rdb
文件,完成持久化。优点 | 缺点 |
---|---|
1. 文件体积小,恢复速度快(全量加载)。 | 1. 无法实时持久化,可能丢失最近写入的数据。 |
2. 适合备份(如定时同步到远程服务器)。 | 2. fork 子进程时可能占用大量内存和 CPU。 |
3. 跨版本兼容性好(不同 Redis 版本可读取)。 | 3. 大内存实例 fork 时可能导致短暂阻塞。 |
# 自动触发规则(可配置多个条件,用空格分隔)
save 900 1 # 900秒内至少1次写操作
save 300 10 # 300秒内至少10次写操作
save 60 10000 # 60秒内至少10000次写操作
stop-writes-on-bgsave-error yes # 快照失败时禁止写入(避免数据不一致)
rdbcompression yes # 是否压缩数据(牺牲CPU换取空间)
rdbchecksum yes # 写入时校验数据(增加文件生成时间)
dbfilename dump.rdb # 快照文件名
dir ./ # 快照存储目录(需提前创建,权限可写)
SET
/HSET
等)按协议格式追加到 AOF 文件末尾,读命令不记录。INCR
同一个键),通过 BGREWRITEAOF
命令优化:
SET
替代多次 INCR
)。auto-aof-rewrite-percentage
(默认 100%,即文件大小较上次重写后增长 100%)和 auto-aof-rewrite-min-size
(默认 64MB,文件最小体积)。BGREWRITEAOF
。优点 | 缺点 |
---|---|
1. 数据安全性高(可配置每秒或实时刷盘)。 | 1. 文件体积通常大于 RDB(记录所有写命令)。 |
2. 支持实时持久化(根据 fsync 策略)。 | 2. 恢复速度较慢(需重放所有命令)。 |
3. 日志文件可读(便于排查问题)。 | 3. 重写时可能消耗大量 CPU 和 I/O。 |
appendonly yes # 启用 AOF(默认关闭)
appendfilename "appendonly.aof" # AOF 文件名
appendfsync always # 刷盘策略:
# always:每个写命令都刷盘(最慢,数据安全性最高)
# everysec:每秒刷盘(推荐,兼顾性能与安全)
# no:由操作系统决定(最快,风险高)
no-appendfsync-on-rewrite yes # 重写时是否停止刷盘(避免阻塞)
auto-aof-rewrite-percentage 100 # 触发重写的文件增长百分比
auto-aof-rewrite-min-size 64mb # 触发重写的最小文件大小
aof-load-truncated yes # 加载时忽略损坏的日志(避免启动失败)
aof-use-rdb-preamble yes # 混合持久化时,在 AOF 开头添加 RDB 内容
redis-check-aof --fix
工具修复。aof-use-rdb-preamble yes # 开启混合持久化(默认开启)
维度 | RDB | AOF |
---|---|---|
数据安全 | 低(可能丢失最后一次快照后的数据) | 高(取决于 fsync 策略) |
文件体积 | 小(压缩后) | 大(原始命令日志) |
恢复速度 | 快(全量加载) | 慢(重放所有命令) |
性能影响 | fork 时可能阻塞主线程 | 每秒刷盘几乎无阻塞,always 会降低写入性能 |
适用场景 | 备份、主从同步、允许少量数据丢失 | 金融交易、实时数据要求高的场景 |
Redis 的过期键删除策略采用 被动删除(惰性删除) 和 主动删除(定期删除) 结合的方式,并在内存不足时触发 内存淘汰机制。以下是具体策略的详细说明:
策略 | 触发条件 | 执行逻辑 | 优点 | 缺点 |
---|---|---|---|---|
惰性删除 | 客户端访问键时 | 检查键是否过期: - 过期则删除并返回 nil - 未过期则正常处理请求 |
不主动消耗 CPU 资源 | 可能导致过期键长期占用内存 |
适用场景 | 读多写少、过期键易被访问 | — | — | — |
策略 | 触发条件 | 执行逻辑 | 优点 | 缺点 |
---|---|---|---|---|
定期删除 | 周期性任务(默认每 100ms) | 1. 从每个数据库随机抽样少量键(默认 20 个) 2. 删除其中过期的键 3. 若过期键比例 > 25%,重复抽样(最多循环 ACTIVE_EXPIRE_CYCLE_LOOP 次,单次耗时 ≤ 25ms) |
主动清理过期键,避免内存泄漏 | 无法保证即时删除所有过期键 |
配置参数 | hz (默认 10,即每秒 10 次) |
— | 增大 hz 提升清理频率 |
增大 hz 会增加 CPU 消耗 |
当内存使用达到 maxmemory
限制时,强制删除键(包括未过期键),优先淘汰过期键或符合策略的键:
策略 | 作用范围 | 淘汰逻辑 |
---|---|---|
volatile-ttl |
仅设置过期时间的键 | 优先删除剩余存活时间(TTL)最短的键 |
volatile-random |
仅设置过期时间的键 | 随机删除设置过期时间的键 |
volatile-lru |
仅设置过期时间的键 | 淘汰最近最少使用(LRU)的键 |
volatile-lfu |
仅设置过期时间的键 | 淘汰最不常用(LFU)的键 |
allkeys-random |
所有键(无论是否过期) | 随机删除任意键 |
allkeys-lru |
所有键(无论是否过期) | 淘汰最近最少使用(LRU)的键 |
allkeys-lfu |
所有键(无论是否过期) | 淘汰最不常用(LFU)的键 |
noeviction (默认) |
所有键 | 禁止删除任何键,写入操作报错 |
Redis 的事务(Transaction)提供了一种将多个命令组合执行的机制,确保多个操作按顺序执行,但不支持回滚(Rollback),主要用于简化批量操作和处理并发场景。以下是 Redis 事务的核心概念、命令、流程及特性的详细说明:
命令 | 作用 |
---|---|
MULTI |
开启事务,标记后续命令进入队列(排队阶段),返回 OK 。 |
EXEC |
执行事务队列中的所有命令,返回各命令的结果列表;若中途监控键被修改,返回 nil 。 |
DISCARD |
放弃事务,清空队列并退出事务,返回 OK 。 |
WATCH key [key ...] |
监控一个或多个键,若事务执行前(EXEC 前)键被修改,则事务自动失败(EXEC 返回 nil )。 |
UNWATCH |
取消所有监控,用于主动放弃监控机制。 |
2.1.开启事务
127.0.0.1:6379> MULTI
OK # 进入事务模式,后续命令入队
2.2. 命令入队(Queue Commands)
SET
、GET
等),命令不会立即执行,而是加入事务队列,返回 QUEUED
。EXEC
时会拒绝执行整个事务。 127.0.0.1:6379> SET key1 "value1" # 入队成功,返回 QUEUED
QUEUED
127.0.0.1:6379> INVALID_COMMAND # 语法错误,入队失败,标记事务为 discard
(error) ERR unknown command `INVALID_COMMAND`
2.3. 执行事务(EXEC)或放弃事务(DISCARD)
EXEC
按顺序执行所有命令,返回结果列表。 127.0.0.1:6379> EXEC # 执行事务
1) OK # SET key1 "value1" 的结果
2) (error) ERR unknown command `INVALID_COMMAND` # 语法错误的命令导致执行失败
DISCARD
会清空队列,退出事务模式。 127.0.0.1:6379> DISCARD
OK
特性 | Redis 事务 | 传统数据库事务 |
---|---|---|
原子性(Atomicity) | 队列中的命令要么全部执行,要么全部不执行(仅在入队阶段有语法错误时); 执行阶段单命令失败不影响其他命令。 |
整个事务要么全部成功,要么回滚。 |
一致性(Consistency) | 保证事务执行前后数据状态合法(依赖应用层逻辑)。 | 事务执行前后数据满足完整性约束。 |
隔离性(Isolation) | 命令按入队顺序串行执行,无并发问题(单线程模型)。 | 支持多种隔离级别(如读未提交、可重复读)。 |
持久性(Durability) | 取决于持久化策略(RDB/AOF),与事务无关。 | 由数据库持久化机制保证(如 WAL 日志)。 |
4、乐观锁机制:WATCH 命令
作用
流程示例
balance
: 127.0.0.1:6379> WATCH balance # 监控账户余额
OK
127.0.0.1:6379> GET balance
"100"
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECR balance # 扣款 1 元,入队
QUEUED
balance
(模拟并发修改): 127.0.0.1:6379> SET balance "90" # 其他操作修改了余额
OK
127.0.0.1:6379> EXEC # 发现 balance 被修改,事务失败,返回 nil
(nil)
127.0.0.1:6379> UNWATCH # 取消监控,重新开始流程
OK
5、事务的局限性
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET key "value" # 入队成功
QUEUED
127.0.0.1:6379> LPUSH key "element" # 类型错误(key 是字符串,非列表)
QUEUED
127.0.0.1:6379> EXEC
1) OK # SET 成功
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value # LPUSH 失败
WATCH
仅能监控键是否被修改,无法处理复杂的业务逻辑冲突(如金额计算错误),需应用层处理。5、适用场景
WATCH
防止并发修改(如库存扣减、账户余额调整)。Redis 提供了多种集群方式以满足不同的业务需求,主要包括 主从复制(Master-Slave Replication)、哨兵模式(Sentinel)和 集群模式(Cluster)。以下是各模式的详细对比和说明:
RDB
快照和增量日志(AOF
重写)向从节点同步数据。优点 | 缺点 |
---|---|
- 配置简单,易于实现 | - 主节点单点故障,需手动切换 |
- 支持读写分离 | - 无法自动恢复,存在服务中断风险 |
- 适合读多写少场景 | - 从节点数据可能存在延迟(异步复制) |
PING
命令检查主从节点存活状态。ODOWN
),触发选举机制,选择最优从节点(如复制偏移量最大、优先级最高)。优点 | 缺点 |
---|---|
- 自动故障转移,高可用 | - 不支持数据分片,单机存储限制 |
- 多哨兵节点避免单点故障 | - 主节点写压力大,无法横向扩展数据量 |
- 兼容主从复制的读写分离 | - 故障转移期间存在短暂服务不可用 |
16384
个哈希槽,每个主节点负责部分槽位。Gossip 协议
交换集群状态,自动发现和维护节点关系。CRC16(key) % 16384
计算槽位,映射到对应主节点。例如: 槽位 0-5460 → 节点 A
槽位 5461-10922 → 节点 B
槽位 10923-16383 → 节点 C
优点 | 缺点 |
---|---|
- 支持数据分片,突破单机存储限制 | - 配置和管理复杂(需手动分配槽位) |
- 高可用性(主从 + 自动故障转移) | - 客户端需支持集群模式(如 Redis-Py Cluster) |
- 读写性能可线性扩展 | - 跨节点操作需通过路由,存在延迟 |
- 适合大数据量和高并发场景 | - 不支持多键事务(仅支持单槽操作) |
维度 | 主从复制 | 哨兵模式 | 集群模式 |
---|---|---|---|
高可用性 | 手动切换,低 | 自动故障转移,高 | 自动故障转移,高 |
数据分片 | 不支持 | 不支持 | 支持(16384 哈希槽) |
读写扩展 | 读可扩展(从节点) | 读可扩展(从节点) | 读写均可扩展(节点) |
单机瓶颈 | 主节点存在 | 主节点存在 | 无(数据分散存储) |
部署复杂度 | 简单 | 中等(需配置哨兵) | 复杂(槽位管理) |
典型场景 | 备份、读写分离 | 高可用中小规模数据 | 大规模数据 / 高并发 |
Redis 版本 | 2.0+ | 2.8+ | 3.0+ |
在 Redis 缓存体系中,“缓存三兄弟” 通常指的是缓存穿透、缓存击穿和缓存雪崩,这三个是缓存场景中常见的典型问题,会严重影响系统性能甚至导致服务崩溃。以下是对它们的详细解析:
布隆过滤器(Bloom Filter)
空值缓存
参数校验
热点数据永不过期
加互斥锁(Mutex)
SET NX
命令实现分布式锁(如 set lock_key unique_value nx px 10000
)。提前更新缓存
分散过期时间
TTL = 3600 + random(600)
),避免大量键同时过期。提升缓存高可用性
熔断降级
限流
二级缓存
问题 | 核心原因 | 典型场景 | 解决方案核心思路 |
---|---|---|---|
缓存穿透 | 请求不存在的数据 | 恶意攻击、非法参数查询 | 过滤无效请求、缓存空值 |
缓存击穿 | 单个热点键过期,并发请求 | 热点商品秒杀、突发流量 | 避免并发重建、延长热点键存活 |
缓存雪崩 | 大量键过期或缓存服务不可用 | 批量缓存到期、Redis 宕机 | 分散过期时间、增强系统容错 |