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、最佳实践
- 加前检查
需限制最大值时,Lua 脚本if new>cap then return err end
。 - 乐观锁
多字段同时递增:WATCH key
→ 取值 → 计算 →MULTI
+NUMINCRBY
。 - 流水线计数
批量不同键计数可 Pipeline 多条NUMINCRBY
,吞吐最大化。 - 监控阈值告警
递增后直接比较返回新值,大于阈值即发布告警。
7、总结
JSON.NUMINCRBY
把 原子自增 带到 JSON 世界,让嵌套数值像字符串计数器一样易用且高效:
- O(1) 更新单路径
- 无 GET/SET 往返,并发安全
- 通配递归 批量更新
配合 JSON.MGET / MSET / MERGE
等批量读写指令,你可以轻松构建高吞吐的计数系统、排行榜、库存管理和实时监控。赶快把 NUMINCRBY
融入你的业务逻辑,让每一次“+1”都既精准又飞快!🚀