Redis 8.8 新特性实操笔记:原生数组、INCREX 限流、XNACK 流处理
先说结论(省得滑到底)
如果你现在正用 Lua 脚本做限流、用 List 模拟滑动窗口、或对流消息的失败处理有实时性要求,这版能直接少写代码。其余是性能和小增强,按需取。生产环境请用 8.8.1——8.8.0 有多个 RESTORE 相关的远程代码执行漏洞,已在 8.8.1 修掉。
背景:从 2009 到 8.8
Redis 从 2009 年发布起就用五大基础类型:String、List、Hash、Set、Sorted Set。这么多年一直有一类需求没被原生覆盖——按数字下标快速存取一串字符串。想要这个能力,以前只能三选一:用 List 模拟、把数据塞进 JSON、或者自己写 Lua。三种都用着别扭。
2025 年的 8.0 是个节点:开源协议改回 AGPLv3,JSON、时序、向量这些模块能力并进核心。之后从 8.0 到 8.8 迭代明显加快——8.2 简化 Stream 多消费组、8.4 让消费者更易读新增与空闲消息、8.6 加幂等生产。8.8 干的事比较实在:把几个最常用的模式做成了原生命令,不用再靠 Lua 和客户端逻辑拼。
下面按新结构、限流、流消息、周边增强、性能与落地几块讲,命令都给可直接在 redis-cli 里敲的版本,文末附一份上线前 checklist。
目录
- 原生数组 Array
- INCREX 限流
- XNACK 流消息
- 一批小增强(Hash / TS / JSON / ZSet)
- 性能与落地
PART 01 原生数组 Array:终于能按下标存了
8.8 新增了 Array 类型(由 @antirez 提交)。它是一个按数字下标存取的字符串集合,动态扩容、稀疏下标友好,并且支持服务端聚合(SUM/MIN/MAX 直接在 Redis 内算,不用把数据拉回客户端)。
常用命令(可直接抄)
# 从下标 0 连续写入
ARSET seats:A1 0 "free" 1 "sold" 2 "lock"
ARGET seats:A1 1 # 读单个下标 → "sold"
ARLEN seats:A1 # 总长度(最大下标+1)
ARCOUNT seats:A1 # 实际有值的槽位数(稀疏友好)
ARINFO seats:A1 FULL # 看元数据 / slice 统计
滑动窗口:ARRING 比 RPUSH+LTRIM 快一倍
维护「最近 N 条」这类窗口,经典写法是 RPUSH 追加 + LTRIM 截断。8.8 提供了 ARRING 命令,专门把数组当定长环缓冲用,官方在同机基准下吞吐比 RPUSH+LTRIM 高约 2 倍,且和环大小无关。读窗口用 ARLASTITEMS。
# 行情滑窗:新报价写入尾部
ARRING prices:600519 1820.50 1821.10 1822.30
# 取最近 300 条展示
ARLASTITEMS prices:600519 300
# 服务端聚合(不拉数据回客户端)
AROPSUM prices:600519 # 求和
ARGREP prices:600519 "182*" # 类 grep 检索
CASE 01|选座 / 货位 / 充电桩:位置本身就是下标
一排座位、一排充电桩、一排快递柜,哪个位置空闲/占用/维修,按下标读写最贴合业务直觉,不必把每个格子拆成独立 key。稀疏数组直接用 ARCOUNT 就能知道实际占用多少,不用遍历。
⚠️ 什么时候别用:Array 不是 List/Hash/ZSet 的替代品。需要 push/pop 或中间插入用 List;需要字段名访问用 Hash。另外官方实测 Array 比 List 多占用约 18% 内存——初版大数组上线前先用
MEMORY USAGE看一眼。
PART 02 INCREX:限流不用再写 Lua
限流是 Redis 最高频的用途之一。过去要实现「每分钟 100 次」这种窗口计数,基本人手一段 Lua 脚本,或者用 MULTI/EXEC 包 INCR+EXPIRE。8.8 把这事做成了一条原子命令 INCREX:递增、上下界、过期一次搞定,少一次网络往返。
真实语法(注意不是三个位置参数)
INCREX key [BYFLOAT f | BYINT i]
[LBOUND lo] [UBOUND hi]
[OVERFLOW WRAP|SAT|FAIL]
[EX s|PX ms|...|PERSIST] [ENX]
# 每用户每分钟≤100次:上限100,60s窗口
INCREX api:user:42:req BYINT 1 UBOUND 100 EX 60
# → 返回 [当前计数, 实际增量],如 [3,1]放行 / [100,0]拒绝
# 防爆破:错误上限5,到顶截断不报错
INCREX login:fail:u1001 BYINT 1 UBOUND 5 EX 60 SATURATE
几个关键点:返回值同时给出新计数和实际增量,调用方据此判断放行还是拒绝;UBOUND 是上限,超了直接拒绝;SATURATE 则「部分接受」,计数器截到上限、返回实际接受的增量(适合防爆破锁账号);ENX 只在 key 首次创建时设过期,避免每次请求都把窗口 TTL 重置。
迁移对照:原来怎么写
8.8 之前最常见的固定窗口限流用的是这段 Lua(INCR+边界判断+EXPIRE 包在一起保证原子):
-- ratelimit.lua(经典写法)
local cur = redis.call('incr', KEYS[1])
if cur == 1 then
redis.call('expire', KEYS[1], ARGV[1])
end
if cur > tonumber(ARGV[2]) then return 0 end
return 1
现在上面这一段可以直接删掉,换成一条 INCREX。少维护一份脚本、少一次往返,边界语义还更全(SATURATE、ENX 都是原来要自己写的)。
CASE 02|中后台 API 限流 + 防爆破登录 + 防短信轰炸
三类都是「计数+限时+可能要上限」的窗口场景:API 每用户每分钟 100 次;同一账号连续输错密码 5 次临时锁 60 秒;同一手机号 60 秒内最多发 1 条验证码。用 INCREX 一把梭,返回的实际增量就是「这次放行没」的判断依据。
⚠️ 上手提示:INCREX 的语法在 RC1→GA 之间改过(修复 #15237)。如果你在 RC 阶段就写过相关逻辑,上线前务必按 8.8.1 文档重测一遍,别直接搬 RC 的参数顺序。
PART 03 XNACK:流消息能主动「甩锅」了
Stream 多消费者协作时,消费者 XREADGROUP 读到消息、还没 XACK 就崩溃或处理失败,消息会卡在 PEL(待处理列表) 里。以前只能等别的消费者靠 XAUTOCLAIM/XCLAIM 超时回收——消息要闲置一阵才能被接手,对实时系统不友好。
8.8 加了 XNACK:处理失败的消费者可以显式把这条消息释放回 PEL,立刻可被其他消费者认领重投,不用干等回收周期。它和 XACK 的区别很直接:XACK 是「成功了,删掉」;XNACK 是「我没处理好,放回给别的人」。
三种模式对应三种失败
- SILENT:失败和消息本身无关(服务重启、瞬时错误),递减送达计数,消息排回 PEL 头部重试。
- FAIL:本消费者没资源处理(CPU/内存),计数不变,优先分给其他消费者。
- FATAL:毒消息(格式错、恶意),送达计数设为 LLONG_MAX,等人工介入,不再自动重投。
XREADGROUP GROUP order-g c1 COUNT 1 STREAMS orders >
# 处理失败,主动释放这条消息
XNACK orders order-g FAIL IDS 1 123-0
# 其他消费者立刻能认领(仍需主动来 claim)
XAUTOCLAIM orders order-g c2 0 0-0
CASE 03|订单流水线:消费者崩溃,同伴秒级接手
消费者 C1 处理订单时宕机,C2 不必等默认回收周期(可能数分钟),而是 C1 在退出前主动 XNACK FAIL,C2 马上 XAUTOCLAIM 认领。体验差别就是「卡单」和「秒级恢复」。注意:XNACK 之后消息仍在 PEL,需要别的消费者来 claim 才会真正重投,别指望它自动飞走。
PART 04 一批小增强:单独不大,合起来省往返
Hash 字段级通知
7.4 的 Hash 字段过期(HEXPIRE)很实用,但原来只能收到 key 级事件。8.8 加了 subkey 通知——能订阅字段级的过期/删除,事件里带 key、字段名和类型。缓存失效、审计类场景不用再轮询或全 key 监听。
时序多聚合单命令
蜡烛图这类要同时算 MIN/MAX/FIRST/LAST 的图表,以前要发多条命令。8.8 让 TS.RANGE 等一次返回多种聚合:
TS.RANGE sensor:temp - + AGGREGATION avg 60000 \
AGGREGATION max 60000
JSON 浮点精度可控
JSON.SET 新增 FPHA 参数,可显式指定 BF16/FP16/FP32/FP64。存向量嵌入或传感器读数时,按源数据精度在内存和精度之间权衡,不用一刀切。
ZSet 新增 COUNT 聚合器
ZUNION/ZINTER 等集合运算支持 COUNT 聚合:每个元素的 score 反映它出现在几个输入集合里。标签重合度、去重统计这类需求多一个原生玩法:
ZUNION 2 zset1 zset2 AGGREGATE COUNT WITHSCORES
FT.HYBRID KNN 增强
向量混合检索 FT.HYBRID 支持 KNN 子句里每分片更少候选,并新增 FT.PROFILE HYBRID 做性能剖析。大规模向量检索时,这是个「用召回换延迟」的旋钮——先用 FT.PROFILE 量一遍再调生产。
PART 05 性能数字 + 上线前清单
8.8 在多处端到端吞吐做了优化。下面是官方给的一组数字——但先泼盆冷水:这是 Redis 官方在 Intel Sapphire Rapids m7i.metal-24xl 单实例上的基准,你的机器、数据分布、客户端链路不一样,别直接当承诺。真要信,自己跑一遍:
redis-benchmark -t set,get,mset -n 1000000 -q
| 数据类型/操作(官方基准) | 提升幅度 |
|---|---|
| Strings · MGET(IO 线程) | 最高 +68% |
| Streams · XREADGROUP(COUNT 100) | 最高 +83% |
| Sorted Set · ZADD/ZINCRBY | 最高 +74% |
| 扫描类 SCAN/HSCAN/SSCAN/ZSCAN | 最高 +40% |
| Hash · HGETALL(1K+ 字段) | 最高 +25% |
| Bitmap 操作(x86) | 最高 +28% |
| HyperLogLog · PFCOUNT(x86) | 最高 +18% |
| 持久化与全量复制 | 最高快 60% |
底层还有几处通用优化:x86 版默认开 LTO 链接时优化、部分代码迁到 Rust 降低 FFI 开销、ARM64 专项优化,以及 batched prefetch 批量预取。另外别忘了 Array 比 List 多约 18% 内存——不是纯赚,量级评估时算进去。
上线前 checklist(照着过一遍)
- 版本:生产直接上 8.8.1。8.8.0 有多个 RESTORE 相关 RCE(含 RedisBloom/TimeSeries 模块),公网暴露或处理不可信数据的实例尤其要升。
- 升级顺序:8.x 之间 RDB/AOF 向后兼容,可滚动重启。但 Array/INCREX/XNACK 是新类型和命令,老版本从节点认不出——按「先升从、再切主、最后升老主」的标准滚动流程走。
- 客户端 SDK:go-redis 9.20.0+ 才带 AR*/INCREX/XNACK 封装;老版本用 EVAL/裸命令字符串发也行,但没有类型安全。
- INCREX 语法变了:RC1→GA 改过参数顺序,RC 阶段写的脚本上线前重测。
- 大数组先看内存:初版 Array 上线前用
MEMORY USAGE看一眼,稀疏数组靠ARCOUNT算实际占用。 - 别硬上:Array 不等于 List/Hash;XNACK 之后消息仍在 PEL,记得配
XAUTOCLAIM兜底,别只靠它。
写在最后:要不要升
判断标准很朴实:你现在是不是正被三件事烦——用 Lua 做限流、用 List 维护滑动窗口、流消息只能等超时回收?是的话,8.8 能直接减代码量,升。不是的话,这版对你就是「性能小幅提升 + 几个用不上的命令」,可以等下次大版本再动。
版本上别纠结:8.8.0 于 2026 年 5 月 GA,8.8.1(2026 年 7 月)修了一批安全漏洞,生产直接用 8.8.1 即可。命令细节以官方文档为准,本文命令已在 8.8.1 上核对过语法。
⚠️ 安全提醒:8.8.0 修复了多起 RESTORE 相关的远程代码执行漏洞(CVE-2026-25243 等,含 RedisBloom/TimeSeries 模块)。涉及公网暴露或处理不可信数据的实例,请优先升级到 8.8.1。
我是 {{作者名}},{{一句话简介,如:后端中间件爱好者,喜欢把新版本特性踩完坑再写清楚}}。如果这篇对你有参考价值,欢迎关注,后续会带来更多 Redis 与中间件的落地笔记。
觉得有用就点个赞、在看、转发,让更多被 Lua 限流折磨过的同学看到。
转载请注明出处。
作者:peachyy
出处:http://www.cnblogs.com/peachyy/
出处:https://peachyy.gitee.io/
出处:https://peachyy.github.io/
公众号:

浙公网安备 33010602011771号