Redis 8.8 正式 GA 了。如果你还在跑 8.6,这一版值得认真看——不是小修小补,而是核心数据结构层面的一次补位。Redis 之父 @antirez 亲自下场贡献了 Array 类型,窗口计数器 INCREX 填上了滑动窗口计数的空白,查询层也有多项提速。下面逐项拆开看。
Array:Redis 终于有了原生数组
过去在 Redis 里存一组有序元素,你能选的方案都不太舒服:List 是双端链表,中间插入 O(n);Sorted Set 按分数排序,不适合纯序号场景;用 JSON/HASH 包一层,又多了一层编解码开销。Array 直接解决了这个问题——原生、有序、支持按索引读写。
核心操作大致如下:
| 命令 | 作用 |
|---|---|
ARRAY.PUSH |
尾部追加元素 |
ARRAY.POP |
尾部弹出 |
ARRAY.INSERT |
指定位置插入 |
ARRAY.RANGE |
按索引范围读取 |
ARRAY.LEN |
返回长度 |
ARRAY.SET |
按索引覆写某位 |
一个典型场景:用户的消息收件箱,需要按时间顺序存储、支持分页拉取、偶尔插入一条置顶消息。
# 创建数组并追加消息
ARRAY.PUSH inbox:user:1001 "系统通知:您的订单已发货"
ARRAY.PUSH inbox:user:1001 "客服回复:退款已处理"
ARRAY.PUSH inbox:user:1001 "活动提醒:限时秒杀开始"
# 查看长度
ARRAY.LEN inbox:user:1001
# => 3
# 分页拉取最新 2 条(倒序 range)
ARRAY.RANGE inbox:user:1001 -2 -1
# => "客服回复:退款已处理" "活动提醒:限时秒杀开始"
# 在第 0 位插入一条置顶消息
ARRAY.INSERT inbox:user:1001 0 "置顶:账户安全提醒"
# 覆写某条消息
ARRAY.SET inbox:user:1001 2 "活动提醒:秒杀已结束"
对比 List 的 LINSERT,Array 的 INSERT 在底层实现上做了优化,小规模数组中间插入的实际开销更低。如果你的有序集合长度在几百到几千这个量级、且需要按索引精准操作,Array 比 List 更合适。
注意:Array 是 8.8 新增命令,客户端库可能尚未封装,早期可直接用原始命令发送。生产上线前建议在测试环境验证内存占用与大数组操作延迟。
INCREX:滑动窗口计数,一行命令搞定
限流、风控、实时统计里最常见的需求:"过去 N 秒内发生了多少次"。以前的做法要么用 Sorted Set + 时间戳分数手动算窗口,要么靠 Lua 脚本拼凑,逻辑不复杂但每次都要写一遍。INCREX 把这件事变成了单命令操作。
基本语义:
INCREX key <timestamp> <window-size> [value]
timestamp:当前事件时间戳(毫秒或秒,取决于你选的精度)window-size:窗口长度,同一单位- 可选
value:增量,默认 1
返回值是当前窗口内的累计计数。
一个实际例子——API 限流,每用户 60 秒内最多 100 次请求:
# 每次请求进来时执行
INCREX ratelimit:user:42 1720000000 60
# => 返回当前窗口累计值,比如 73
# 业务侧判断
if result > 100:
return 429 Too Many Requests
对比传统 Sorted Set 方案:
# 旧方案:至少三步操作
ZADD ratelimit:user:42 1720000000 "req:1720000000"
ZREMRANGEBYSCORE ratelimit:user:42 -inf 1719999940
ZCARD ratelimit:user:42
# 还要定期清理过期成员,否则内存持续膨胀
INCREX 的优势很明显:一行命令,原子操作,窗口自动滑动,过期数据自动淘汰。不需要额外清理逻辑,也不需要 Lua 脚本保证原子性。
如果要做更精细的多级限流(比如同时限制每秒和每分钟),可以维护两个 key:
INCREX ratelimit:user:42:sec 1720000000 1 # 1 秒窗口
INCREX ratelimit:user:42:min 1720000000 60 # 60 秒窗口
查询优化与可观测性
8.8 在查询层做了几项务实改进:
- 聚合查询加速:对
SUM、MIN、MAX等聚合操作的内部路径做了优化,大数据集下延迟明显下降。 - 索引扫描改进:FT.SEARCH 在多条件组合查询时减少了不必要的全索引遍历,复合条件查询提速。
- 运行时指标增强:新增了更细粒度的
INFO字段和慢日志分类,可以区分是命令本身慢还是内部数据结构操作慢,排查性能问题不再只能靠猜。
一个快速验证查询提速的方式——用 redis-benchmark 对比 8.6 和 8.8:
# 在 8.6 和 8.8 上分别跑
redis-benchmark -h 127.0.0.1 -p 6379 -t zadd,zcard,zrange -q -c 50 -n 100000
# 对比 QPS 和平均延迟
# 8.8 在 zrange 大范围扫描上通常有 10-30% 提升(取决于数据规模)
上线前检查清单
| 项目 | 建议 |
|---|---|
| 客户端兼容性 | 确认所用客户端库已支持 ARRAY.* 和 INCREX 命令,不支持则用 raw command 发送 |
| 数据迁移 | Array 是新类型,不涉及旧数据迁移,但新写入的 key 在 8.6 上无法读取,降级回滚需提前规划 |
| 内存预估 | Array 在小规模时内存紧凑,万级以上需实测;INCREX 的窗口 key 过期后自动释放,内存可控 |
| 监控告警 | 更新 INFO 解析逻辑,关注新增的慢日志分类字段 |
| 灰度顺序 | 建议先在只读从库或低流量集群验证,再逐步放量到主写入节点 |
Redis 8.8 不是那种"改了几个默认值"的版本。Array 补上了原生有序容器的缺口,INCREX 把滑动窗口计数从手工拼装降到了单命令,查询优化让已有功能跑得更快。如果你的业务里有列表操作、限流计数、聚合查询这三类场景,8.8 的收益是直接的。