一文搞懂Redis
字数 3108 2025-08-11 17:40:17
Redis 深度解析与实战指南
一、Redis核心特性
1.1 Redis高性能原因
- 基于内存操作:所有操作直接在内存中进行,无需磁盘I/O
- 单线程模型:单次执行时间快于线程切换时间
- 高效数据结构:底层采用类似HashMap的k-v结构,查询性能接近O(1)
- I/O多路复用:单个线程通过记录跟踪每个sock(I/O流)状态管理多个I/O流
1.2 其他重要特性
- 丰富数据类型:支持String、Hash、Set、List、Zset等多种数据结构
- 内存管理机制:完善的持久化机制和过期策略
- 多语言支持:提供多种编程语言客户端
- 高可用性:支持主从复制、哨兵、Cluster集群模式
二、Redis数据类型详解
2.1 String类型
基本指令:
MSET key1 value1 key2 value2 # 批量设置
MGET key1 key2 # 批量获取
STRLEN key # 获取长度
APPEND key xxx # 字符串追加
GETRANGE key 0 5 # 获取指定区间字符
INCR intkey # 整数值递增
SETEX key seconds value # 设置带过期时间的值
SETNX key value # 仅当key不存在时设置
应用场景:
- 缓存相关场景
- Token存储(利用过期属性)
- 线程安全的计数场景(限流、分布式ID等)
2.2 Hash类型
基本指令:
HSET key field value # 设置哈希字段
HGET key field # 获取哈希字段
HKEYS key # 获取所有字段
HVALS key # 获取所有值
HINCRBY key field increment # 字段值增加
HEXISTS key field # 检查字段是否存在
应用场景:
- 存储对象类数据
- 统计类数据,可对单个统计字段单独操作
2.3 List类型
基本指令:
LPUSH key value [value ...] # 表头插入
RPUSH key value [value ...] # 表尾插入
LPOP key # 移除并返回表头元素
RPOP key # 移除并返回表尾元素
BLPOP key [key ...] timeout # 阻塞式弹出表头
LINDEX key index # 获取指定位置元素
应用场景:
- 用户消息时间线
- 先进先出/先进后出队列
2.4 Set类型
基本指令:
SADD key member [member ...] # 添加元素
SMEMBERS key # 获取所有成员
SCARD key # 获取元素数量
SRANDMEMBER key [count] # 随机获取元素
SPOP key # 随机移除元素
SREM key member [member ...] # 移除元素
SISMEMBER key member # 检查成员是否存在
SDIFF key1 key2 # 差集
SINTER key1 key2 # 交集
SUNION key1 key2 # 并集
应用场景:
- 抽奖功能
- 点赞、签到等场景
- 关注关系处理
2.5 ZSet(Sorted Set)
基本指令:
ZADD key score member # 添加带分数成员
ZRANGE key start stop # 按分数升序获取
ZREVRANGE key start stop # 按分数降序获取
ZRANGEBYSCORE key min max # 获取分数区间成员
ZREM key member # 移除成员
ZCARD key # 获取成员数量
ZINCRBY key increment member # 增加成员分数
ZCOUNT key min max # 统计分数区间成员数
ZRANK key member # 获取成员排名
应用场景:
- 排行榜功能
- 带权重的队列处理
三、Redis事务
3.1 基本操作
MULTI # 开启事务
SET k1 v1 # 命令入队
SET k2 v2 # 命令入队
EXEC # 提交事务
DISCARD # 取消事务
3.2 事务特性
- 隔离性:事务中的命令序列化执行,不被其他客户端打断
- 无隔离级别:事务提交前命令不会实际执行
- 不保证原子性:某条命令失败后,后续命令仍会执行
四、Redis数据结构实现
4.1 字典(dict)结构
Redis使用字典作为主要数据结构,核心结构包括:
- redisDb:数据库顶层结构,包含键空间、过期键等字典
- dict:字典结构,包含两个哈希表(dictht)用于渐进式rehash
- dictht:哈希表,包含table数组、大小、掩码和已用节点数
- dictEntry:哈希表节点,包含key、value和next指针
4.2 扩容机制
触发条件:
- 无RDB/AOF子进程时,ht[0].used > size
- 有子进程时,ht[0].used ≥ size×5
扩容步骤:
- 创建新哈希表,大小为ht[0].used×2(向上取2的幂)
- 将ht[1]指向新哈希表
- 设置rehashidx=0开始渐进式rehash
- 完成迁移后,ht[0]=ht[1],重置ht[1]
4.3 渐进式rehash
实现方式:
- CRUD操作时迁移一个桶的数据
- 定时任务进行部分数据迁移
- 每次最多迁移空桶数n×10,防止耗时过长
五、Redis过期策略
5.1 惰性过期
- 原理:访问key时检查是否过期,过期则删除
- 优点:最大化节省CPU资源
- 缺点:可能导致内存中堆积大量过期key
5.2 定期过期
实现流程:
- 定时任务随机扫描设置了过期时间的key
- 从每个哈希桶中最多取20个key检查
- 删除已过期的key
- 若扫描空桶超过400个或删除比例>10%,继续执行
- 最多循环16次,超时则退出
六、Redis淘汰策略
6.1 淘汰策略类型
- noeviction:不淘汰,新写入操作报错(默认)
- allkeys-lru:从所有key中淘汰最近最少使用的
- allkeys-lfu:从所有key中淘汰最不经常使用的
- volatile-lru:从设置了过期时间的key中淘汰LRU
- volatile-lfu:从设置了过期时间的key中淘汰LFU
- allkeys-random:从所有key中随机淘汰
- volatile-random:从设置了过期时间的key中随机淘汰
- volatile-ttl:淘汰剩余存活时间最短的key
6.2 淘汰流程
- 判断内存是否满足指令需求
- 从淘汰池尾部选取最适合淘汰的数据
- 随机取样(maxmemory-samples配置)获取候选key
- 根据淘汰算法选择最适合淘汰的key
- 与淘汰池数据比较,更适合则放入淘汰池
- 按适合程度排序,最适合淘汰的放尾部
- 删除选中key并从淘汰池移除
6.3 LRU算法实现
- 使用24位字段记录对象最后访问时间
- 比较当前时间与对象访问时间
- 计算未访问时间,时间越长越容易被淘汰
- 解决循环问题:时间轮询使用24位最大值
6.4 LFU算法实现
- 使用16位时间+8位计数器(0-255)
- 计数器随时间衰减:
num_periods = LFUTimeElapsed(ldt)/lfu_decay_time - 计数器增长概率:
p = 1.0/(baseval*lfu_log_factor+1) - 解决时效性问题:长时间未访问会减少计数器值
七、Redis持久化
7.1 RDB持久化
触发条件:
- 配置触发:
save 900 1、save 300 10等 - shutdown正常关闭
- flushall指令触发
优势:
- 紧凑型文件,适合备份与灾难恢复
- 最大化性能(fork子进程处理)
- 重启更快
不足:
- 数据安全性较低(时间间隔可能丢失数据)
- 频繁fork消耗CPU资源
7.2 AOF持久化
同步机制:
- always:每次写入都同步,安全但性能差
- everysec:每秒同步(默认),最多丢失1s数据
- no:由操作系统决定同步时机
重写机制:
- fork子进程写入新的基础AOF
- 父进程继续写入增量AOF
- 子进程完成重写后,父进程构建临时清单
- 原子交换清单文件,清理旧文件
混合持久化:
- 4.0+版本支持RDB+AOF混合模式
- 重写时使用RDB格式,后续操作为AOF格式
优势:
- 数据安全性高(最多丢失1s数据)
- 可读性更好(追加日志格式)
- 损坏可修复(redis-check-aof工具)
不足:
- 文件体积通常比RDB大
- 持久化和加载速度较慢
- 重写期间内存消耗较大(7.0前版本)
八、Redis常见问题解决方案
8.1 数据丢失场景
持久化丢失:
- 解决方案:启用AOF,配置合理同步策略
主从切换丢失:
- 原因:主从异步复制期间主节点宕机
- 解决方案:合理配置主从复制策略,监控复制延迟
8.2 缓存问题解决方案
缓存雪崩:
- 现象:大量热点数据同时失效,请求直接打到DB
- 解决方案:
- 保证Redis高可用
- 加互斥锁或队列控制并发
- 错开过期时间(加随机数)
- 定时预先更新缓存
缓存穿透:
- 现象:查询不存在的数据,绕过缓存直接访问DB
- 解决方案:
- 布隆过滤器拦截
- 缓存空值(设置较短过期时间)
- 接口层校验非法请求
缓存击穿:
- 现象:热点key失效瞬间大量并发请求
- 解决方案:
- 互斥锁重建缓存
- 双重检查锁优化性能
- 永不过期策略+后台更新
九、Redis高可用方案
9.1 主从复制
- 异步复制机制
- 读写分离提升性能
- 数据冗余保障安全
9.2 哨兵模式
- 监控主节点状态
- 自动故障转移
- 配置提供者
9.3 Cluster集群
- 数据分片存储
- 自动故障检测与转移
- 无中心架构
- 支持水平扩展
十、Redis性能优化建议
- 合理选择数据结构
- 控制key的大小和数量
- 使用批量操作减少网络开销
- 避免大key(拆分或压缩)
- 合理配置持久化策略
- 适当调整内存淘汰策略
- 监控慢查询并优化
- 合理设置连接池参数
本指南详细介绍了Redis的核心特性和实现原理,包括数据结构、持久化机制、淘汰策略等关键知识点,并提供了常见问题的解决方案和性能优化建议。通过深入理解这些内容,开发者可以更好地利用Redis构建高性能、高可用的应用系统。