Redis 从入门到精通(十四):Redis 7.x 新特性全解 ------ 系列收官之作
一、版本演进速览
Redis 5.0 (2018.10): Stream 类型、ZPOPMIN/ZPOPMAX
Redis 6.0 (2020.04): ACL 2.0、多线程 I/O、TLS、RESP3
Redis 7.0 (2022.04): Multi-Part AOF、listpack 全面替代、Redis Function、ACL 增强
Redis 7.2 (2023.08): 扩展 listpack 覆盖范围、优化内存效率
Redis 7.4 (2024.07): Hash 过期、更优的内存效率
二、Multi-Part AOF:持久化架构重构
这是 Redis 7.0 最重要的改进之一,第三篇已经详细讲过,这里做总结。
2.1 旧版 AOF 的问题
- 重写时一个巨大的内存缓冲区
aof_rewrite_buf,高并发下可能 OOM - 单一 AOF 文件,重写失败时状态不明确
- 文件过大时需要手动 BGREWRITEAOF
2.2 Multi-Part AOF 的改进
bash
# 新架构的文件结构
appendonlydir/
├── appendonly.aof.manifest # 清单文件(总指挥)
├── appendonly.aof.1.base.rdb # Base:RDB 格式的全量快照
├── appendonly.aof.1.incr.aof # Incremental:增量 AOF
└── appendonly.aof.2.incr.aof # 下一个增量文件
核心优势:
| 改进点 | 旧版 | Redis 7.0 |
|---|---|---|
| 重写缓冲区 | 单一大内存缓冲 | 直接写入新的 incr 文件 |
| 增量文件轮转 | 不支持 | 达到阈值自动切新文件 |
| 磁盘空间回收 | 重写后才删旧文件 | 渐进式清理历史文件 |
| 恢复灵活性 | 全有或全无 | 可按 manifest 选择性恢复 |
三、Listpack 全面替代 Ziplist
第二篇详细讲过两者的实现差异,这里聚焦于 Redis 7.x 的迁移进展。
3.1 替代时间线
| 版本 | 进展 |
|---|---|
| Redis 5.0 | listpack 首次引入,仅用于 Stream |
| Redis 7.0 | Hash、ZSet 的小数据编码默认使用 listpack |
| Redis 7.2 | listpack 覆盖范围进一步扩大 |
| Redis 7.4 | ziplist 相关配置项几乎全部移除 |
3.2 迁移配置
bash
# Redis 7.0 的新配置(替代旧的 ziplist 配置)
hash-max-listpack-entries 512 # 替代 hash-max-ziplist-entries
hash-max-listpack-value 64 # 替代 hash-max-ziplist-value
zset-max-listpack-entries 128 # 替代 zset-max-ziplist-entries
zset-max-listpack-value 64 # 替代 zset-max-ziplist-value
# 升级到 Redis 7.2+ 后,旧的 ziplist 配置自动忽略
3.3 为什么一定要换?
连锁更新问题 是 ziplist 的致命缺陷(第二篇第四节的完整推演),listpack 通过去掉 prevlen 字段彻底消除。在高并发写入场景下,ziplist 的连锁更新可能导致毫秒级甚至秒级的延迟抖动------listpack 完全没有这个问题。
四、Redis Function:Lua 脚本的下一代方案
第八篇介绍了 Lua 脚本和 Redis Function 的区别,这里深入。
4.1 Function vs Lua 脚本
bash
# 传统 Lua 脚本
EVAL "return redis.call('GET', KEYS[1])" 1 mykey
# 问题:脚本内容每次传输,SHA1 不可读,重启后缓存丢失
# Redis Function
FUNCTION LOAD "#!lua name=mylib
redis.register_function('my_get', function(keys, args)
return redis.call('GET', keys[1])
end)"
FCALL my_get 1 mykey
# 优势:函数名可读,可持久化,管理方便
bash
# 查看函数库
FUNCTION LIST
# 导出函数库
FUNCTION DUMP
# 恢复函数库
FUNCTION RESTORE <serialized>
# 删除函数库
FUNCTION DELETE mylib
# 查看函数库统计
FUNCTION STATS
4.2 Function 的持久化优势
| 特性 | Lua 脚本 | Redis Function |
|---|---|---|
| 重启后 | 脚本缓存丢失,需重新 SCRIPT LOAD | 函数随 AOF/RDB 持久化,重启后自动恢复 |
| 主从复制 | 脚本内容复制到从库 | 函数定义复制到从库 |
| 管理方式 | SHA1 哈希(不可读) | 函数名(可读) |
| 库组织 | 无 | 函数库(library)组织 |
| RESP3 | 不感知 | 可返回 RESP3 类型 Map/Set |
五、ACL 增强
5.1 ACL 2.0 核心功能
bash
# 创建用户:精细的权限控制
ACL SETUSER app_user on >password123 \
~app:* \ # 只能操作 app:* 前缀的 key
+@read \ # 允许读命令
+@hash \ # 允许 Hash 命令
-@write \ # 禁止写命令
-@dangerous # 禁止危险命令
# 通道权限(Pub/Sub)
ACL SETUSER subscriber on >pass \
&channel:* # 只能订阅特定频道
# 选择器(Selector):多规则组合
ACL SETUSER power_user on >pass \
(~app:* +@all) \ # Selector 1: 对 app:* 有全部权限
(~cache:* +@read) # Selector 2: 对 cache:* 只有读权限
5.2 ACL 日志
bash
# 查看被拒绝的命令
ACL LOG 10
# 重置 ACL 日志
ACL LOG RESET
# 输出
# 1) 1) "count" # 拒绝次数
# 2) "reason" # 拒绝原因
# 3) "context" # 上下文
# 4) "username" # 用户
# 5) "client-info" # 客户端信息
5.3 最佳实践
bash
# 1. 禁用 default 用户
ACL SETUSER default off
# 2. 最小权限原则
ACL SETUSER app on >pass ~app:* +@read +@write -@dangerous
# 3. 定期审计
ACL LIST
ACL LOG 100
# 4. 保存配置
ACL SAVE
六、性能和命令变更
6.1 性能提升
| 优化项 | 版本 | 效果 |
|---|---|---|
| 多线程 I/O | 6.0+ | 网络读写多线程,命令执行仍单线程。io-threads 4 |
| dict 内存优化 | 7.0 | 哈希表内存占用降低约 20% |
| SDS 头优化 | 7.0 | embstr 阈值从 44 字节提升到 44 字节(jemalloc 优化) |
| String 整数编码 | 7.0 | 整数的编码和操作更快 |
| listpack 替代 ziplist | 7.0/7.2 | 消除连锁更新,延迟更稳定 |
6.2 新增命令
bash
# Redis 7.0 新增
SINTERCARD numkeys key [key...] [LIMIT limit] # 交集数量(不返回具体元素)
ZINTERCARD numkeys key [key...] [LIMIT limit] # ZSet 交集数量
EXPIRETIME key # 获取过期时间(Unix 时间戳,秒)
PEXPIRETIME key # 同上,毫秒
SORT_RO key [BY ...] # 排序(只读,不修改原 key)
# Redis 7.2 新增
WAIT replicates timeout # 等待指定数量从库确认(同步复制)
# Redis 7.4 新增
HEXPIRE key seconds [NX|XX|GT|LT] FIELDS num field [field...]
HPEXPIRE key ms [NX|XX|GT|LT] FIELDS num field [field...]
HEXPIRETIME key FIELDS num field [field...]
HTTL key FIELDS num field [field...]
6.3 重点新命令详解
bash
# HEXPIRE: Hash 字段级别过期(7.4 重大更新!)
HSET user:session:1001 token "abc" user_id "1001"
HEXPIRE user:session:1001 3600 FIELDS 1 token
# 只有 token 字段会过期,user_id 不设过期
# SINTERCARD: 高效统计交集数量
# 旧方式:SINTER set1 set2 → SMEMBERS → 数数量(O(N+M+K))
# 新方式:SINTERCARD 2 set1 set2(O(N+M) 且不传输完整数据)
SADD set1 a b c d e
SADD set2 c d e f g
SINTERCARD 2 set1 set2 # 返回 3(c,d,e)
SINTERCARD 2 set1 set2 LIMIT 2 # 返回 2(只要够 2 个就停止)
# SORT_RO: 只读排序
SADD numbers 30 3 22 1
SORT_RO numbers BY * LIMIT 0 2 ASC # 返回 [1, 3],原 key 不变
七、升级建议
7.1 版本推荐
| 当前版本 | 推荐目标 | 理由 |
|---|---|---|
| Redis 5.x | 7.0 | 跨越式升级,获得 Stream + ACL + Function |
| Redis 6.0 | 7.0 / 7.2 | 7.0 稳定,7.2 最新优化 |
| Redis 6.2 | 7.2 | 生产验证充分,listpack 覆盖更广 |
| 新项目 | 7.2 或最新稳定版 | 直接上最新 |
7.2 升级前检查清单
bash
# 1. 检查废弃配置
# ziplist 相关配置改为 listpack
# 旧的 RDB/AOF 文件格式兼容
# 2. 检查命令兼容性
redis-cli --cluster check # 集群模式
INFO replication # 主从状态
# 3. 滚动升级(Cluster / Sentinel)
# 先升级从库 → 故障转移 → 升级旧主库
# 逐个操作,不可全部同时升级
# 4. 监控观察
# 升级后观察 24 小时:内存、延迟、慢查询、主从同步
八、系列总回顾
经过十四篇文章,我们构建了完整的 Redis 知识体系:
#mermaid-svg-AQgmvzVvAlXb31ZE{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-AQgmvzVvAlXb31ZE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AQgmvzVvAlXb31ZE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AQgmvzVvAlXb31ZE .error-icon{fill:#552222;}#mermaid-svg-AQgmvzVvAlXb31ZE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AQgmvzVvAlXb31ZE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AQgmvzVvAlXb31ZE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AQgmvzVvAlXb31ZE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AQgmvzVvAlXb31ZE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AQgmvzVvAlXb31ZE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AQgmvzVvAlXb31ZE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AQgmvzVvAlXb31ZE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AQgmvzVvAlXb31ZE .marker.cross{stroke:#333333;}#mermaid-svg-AQgmvzVvAlXb31ZE svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AQgmvzVvAlXb31ZE p{margin:0;}#mermaid-svg-AQgmvzVvAlXb31ZE .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-AQgmvzVvAlXb31ZE .cluster-label text{fill:#333;}#mermaid-svg-AQgmvzVvAlXb31ZE .cluster-label span{color:#333;}#mermaid-svg-AQgmvzVvAlXb31ZE .cluster-label span p{background-color:transparent;}#mermaid-svg-AQgmvzVvAlXb31ZE .label text,#mermaid-svg-AQgmvzVvAlXb31ZE span{fill:#333;color:#333;}#mermaid-svg-AQgmvzVvAlXb31ZE .node rect,#mermaid-svg-AQgmvzVvAlXb31ZE .node circle,#mermaid-svg-AQgmvzVvAlXb31ZE .node ellipse,#mermaid-svg-AQgmvzVvAlXb31ZE .node polygon,#mermaid-svg-AQgmvzVvAlXb31ZE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AQgmvzVvAlXb31ZE .rough-node .label text,#mermaid-svg-AQgmvzVvAlXb31ZE .node .label text,#mermaid-svg-AQgmvzVvAlXb31ZE .image-shape .label,#mermaid-svg-AQgmvzVvAlXb31ZE .icon-shape .label{text-anchor:middle;}#mermaid-svg-AQgmvzVvAlXb31ZE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-AQgmvzVvAlXb31ZE .rough-node .label,#mermaid-svg-AQgmvzVvAlXb31ZE .node .label,#mermaid-svg-AQgmvzVvAlXb31ZE .image-shape .label,#mermaid-svg-AQgmvzVvAlXb31ZE .icon-shape .label{text-align:center;}#mermaid-svg-AQgmvzVvAlXb31ZE .node.clickable{cursor:pointer;}#mermaid-svg-AQgmvzVvAlXb31ZE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-AQgmvzVvAlXb31ZE .arrowheadPath{fill:#333333;}#mermaid-svg-AQgmvzVvAlXb31ZE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AQgmvzVvAlXb31ZE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AQgmvzVvAlXb31ZE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AQgmvzVvAlXb31ZE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AQgmvzVvAlXb31ZE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AQgmvzVvAlXb31ZE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-AQgmvzVvAlXb31ZE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AQgmvzVvAlXb31ZE .cluster text{fill:#333;}#mermaid-svg-AQgmvzVvAlXb31ZE .cluster span{color:#333;}#mermaid-svg-AQgmvzVvAlXb31ZE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AQgmvzVvAlXb31ZE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AQgmvzVvAlXb31ZE rect.text{fill:none;stroke-width:0;}#mermaid-svg-AQgmvzVvAlXb31ZE .icon-shape,#mermaid-svg-AQgmvzVvAlXb31ZE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AQgmvzVvAlXb31ZE .icon-shape p,#mermaid-svg-AQgmvzVvAlXb31ZE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-AQgmvzVvAlXb31ZE .icon-shape .label rect,#mermaid-svg-AQgmvzVvAlXb31ZE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AQgmvzVvAlXb31ZE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-AQgmvzVvAlXb31ZE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-AQgmvzVvAlXb31ZE :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 运维与未来(13-14)
第十三篇:性能优化与运维
第十四篇:7.x 新特性
高级进阶篇(10-12)
第十篇:高级特性
第十一篇:客户端与连接池
第十二篇:业务场景实战
业务应用篇(7-9)
第七篇:缓存设计
第八篇:事务/Lua/Pipeline
第九篇:分布式锁
基础设施篇(3-6)
第三篇:持久化机制
第四篇:主从复制
第五篇:哨兵 Sentinel
第六篇:集群 Cluster
基础篇(1-2)
第一篇:基础入门
第二篇:深入数据结构
十四篇文章,四个层次:
| 层次 | 篇目 | 核心收获 |
|---|---|---|
| 基础 | 1-2 | 五种类型 + 六大底层结构,理解 Redis "怎么存" |
| 基础设施 | 3-6 | 持久化 → 主从 → Sentinel → Cluster,"越来越稳" |
| 业务应用 | 7-9 | 缓存设计 + 原子操作 + 分布式锁,"从能用到好用" |
| 进阶运维 | 10-14 | 高级特性 + 客户端 + 实战 + 运维 + 新版本 |
本系列到此完结。 从第一篇的
SET key value到最后一篇的Multi-Part AOF和Redis Function,我们走完了 Redis 从入门到精通的全过程。希望这十四篇文章成为你面试复习的知识图谱、生产排障的参考手册、系统设计的灵感来源。感谢阅读。如有疑问或建议,欢迎在每篇文章下方评论交流。