RedisJSON 技术揭秘`JSON.NUMINCRBY` 像 `INCRBY` 一样给 JSON 里的数字加减

发布于:2025-07-21 ⋅ 阅读:(19) ⋅ 点赞:(0)

1、指令速查

JSON.NUMINCRBY <key> <path> <number>
参数 含义
key Redis 键名
path JSONPath,只能指定一次
number 正/负浮点或整数,加到目标值上

返回值:JSON 字符串数组,顺序对应每个匹配到的路径:

  • 成功加减 → 新值字符串
  • 路径不是数字 → null

时间复杂度

  • 单路径 → O(1)
  • 多路径(如 $..score)→ O(N)N 为匹配节点数

2、CLI 实战

2.1 准备文档

JSON.SET player $ '{
  "name":"Alice",
  "stats":{"score":100,"level":3},
  "achievements":[{"score":10},{"score":20},{"score":"n/a"}]
}'

2.2 给单个字段加 5

redis> JSON.NUMINCRBY player $.stats.score 5
"[105]"

2.3 递归给所有 score 加 2

redis> JSON.NUMINCRBY player $..score 2
"[107,12,22,null]"

第 4 个匹配是字符串 "n/a",返回 null

3、跨语言示例

3.1 Python(redis-py ≥ 5.0)

from redis import Redis
r = Redis(decode_responses=True)

new_score = r.execute_command(
    "JSON.NUMINCRBY", "player", "$.stats.score", 5
)
print(new_score)  # ['110']

3.2 Node.js(@redis/client)

import { createClient } from 'redis';
const cli = createClient(); await cli.connect();

const [newLevel] = await cli.json.numIncrBy('player', '$.stats.level', 1);
console.log(newLevel); // "4"

3.3 Go(go-redis/v9)

delta := 2
res, _ := rdb.Do(ctx, "JSON.NUMINCRBY", "player", "$..score", delta).StringSlice()
fmt.Println(res)  // ["109","14","24","null"]

4、典型应用场景

场景 玩法
游戏积分 $..score +1,排行榜实时更新
电商库存 $.stock -1,原子扣减避免超卖
监控计数器 sensor:{id}$.metrics.temp
AB 实验 多路径 $..exposed 递增曝光量

5、坑点与性能提示

坑 / 症状 规避策略
路径非数字 → null 写前先 JSON.TYPE 或捕捉返回值检查
浮点精度 Redis 使用 double;金融场景建议整数分化或字符串存储
大量通配 $..field 线性 O(N);可过滤更具体路径或拆批
集群哈希槽 单键操作无跨槽风险;但若 Pipeline 多键需注意
并发+写扩散 对热点键高并发 NUMINCRBY 会锁 Redis 主线程;考虑分片或拆子键

6、最佳实践

  1. 加前检查
    需限制最大值时,Lua 脚本 if new>cap then return err end
  2. 乐观锁
    多字段同时递增:WATCH key → 取值 → 计算 → MULTI + NUMINCRBY
  3. 流水线计数
    批量不同键计数可 Pipeline 多条 NUMINCRBY,吞吐最大化。
  4. 监控阈值告警
    递增后直接比较返回新值,大于阈值即发布告警。

7、总结

JSON.NUMINCRBY原子自增 带到 JSON 世界,让嵌套数值像字符串计数器一样易用且高效:

  • O(1) 更新单路径
  • 无 GET/SET 往返,并发安全
  • 通配递归 批量更新

配合 JSON.MGET / MSET / MERGE 等批量读写指令,你可以轻松构建高吞吐的计数系统、排行榜、库存管理和实时监控。赶快把 NUMINCRBY 融入你的业务逻辑,让每一次“+1”都既精准又飞快!🚀


网站公告

今日签到

点亮在社区的每一天
去签到