RedisJSON 指令精讲JSON.TOGGLE 键翻转布尔值
1 · 为什么要学 JSON.TOGGLE?
在特性开关、状态机、AB 实验、勾选框等场景下,我们经常需要把 true
↔ false
来回切换。传统做法要先 JSON.GET
读出布尔值、在客户端翻转、再 JSON.SET
写回;这不仅多一次 RTT,还增加竞态风险。JSON.TOGGLE
直接在 Redis 端 原子翻转 布尔字段,让代码更简洁、操作更安全。
2 · 指令概览
JSON.TOGGLE key [path]
- 可用版本:RedisJSON ≥ 2.0.0
- ACL 标签:
@json @write @slow
- 默认路径:
$
(根)
3 · 语法解析
JSON.TOGGLE []
key
path
$
返回值
- 布尔 → 数字:翻转后值,
1
代表true
,0
代表false
- 多路径:数组形式,顺序与匹配点一致
- 非布尔:返回
nil
- 路径不存在:同样返回
nil
4 · 实战示例
redis> JSON.SET feature $ \'{\"enabled\":true,\"nested\":{\"flag\":false},\"id\":123}\'OK# ➊ 单路径翻转redis> JSON.TOGGLE feature $.enabled1) (integer) 0 # false# ➋ 多路径翻转redis> JSON.TOGGLE feature $..flag1) (integer) 1 # nested.flag false → true# ➌ 非布尔字段redis> JSON.TOGGLE feature $.id1) (nil)redis> JSON.GET feature $\"[{\\\"enabled\\\":false,\\\"nested\\\":{\\\"flag\\\":true},\\\"id\\\":123}]\"
5 · 典型使用场景
JSON.MGET
批量查开关 + JSON.TOGGLE
动态翻转done
→ true
TOGGLE
复位locked
) 字段 true/falseWATCH
做乐观锁groupA
字段做对照JSON.TOGGLE
6 · 踩坑与注意
nil
,值不变JSON.TYPE
校验$..flag
通配,改用精确路径NX/XX
或 Lua 脚本加条件判断7 · Go-Redis 完整示例
依赖:
github.com/redis/go-redis/v9
、RedisJSON ≥ 2.0
package mainimport (\"context\"\"fmt\"\"log\"\"github.com/redis/go-redis/v9\")func main() {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: \"localhost:6379\"})defer rdb.Close()// 1️⃣ 初始化文档_, err := rdb.Do(ctx, \"JSON.SET\", \"task:1001\", \"$\",`{\"title\":\"write blog\",\"done\":false}`).Result()if err != nil { log.Fatal(err) }// 2️⃣ 原子翻转 doneres, _ := rdb.Do(ctx, \"JSON.TOGGLE\", \"task:1001\", \"$.done\").Slice()fmt.Println(\"done =\", res[0]) // 1 (true)// 3️⃣ 再次翻转以复位rdb.Do(ctx, \"JSON.TOGGLE\", \"task:1001\", \"$.done\")// 4️⃣ 读取验证state, _ := rdb.Do(ctx, \"JSON.GET\", \"task:1001\", \"$.done\").Text()fmt.Println(\"current done:\", state) // false}
批量翻转示例(Pipeline)
pipe := rdb.Pipeline()keys := []string{\"task:1\", \"task:2\", \"task:3\"}for _, k := range keys {pipe.Do(ctx, \"JSON.TOGGLE\", k, \"$.done\")}if _, err := pipe.Exec(ctx); err != nil {log.Fatal(err)}
8 · 性能与并发建议
-
Pipeline / Lua 脚本
-
高并发批量翻转时使用 Pipeline 减少 RTT。
-
若需条件判断(如仅当
done=false
才翻转),可写 Lua:local v=redis.call(\'JSON.GET\',KEYS[1],\'$.done\')if v==\'false\' then return redis.call(\'JSON.TOGGLE\',KEYS[1],\'$.done\')[1]endreturn -1
-
-
慢日志监控
- 大文档 + 多路径 (
$..flag
) 易触发SLOWLOG
。
- 大文档 + 多路径 (
-
幂等 API
- Web 接口里应返回翻转后值,而不是固定 200 来避免并发写乱序。
9 · 与其他指令的协同
JSON.SET ... NX
→ JSON.TOGGLE
NX
保证类型,后续直接翻转FT.AGGREGATE
+ JSON.TOGGLE
JSON.SET
+ JSON.TOGGLE
10 · 小结
- JSON.TOGGLE 为布尔字段提供了 原子取反 能力,消除读-改-写竞态。
- 返回值
1
/0
表示翻转后的 true / false,可直接用作状态。 - 多路径场景要注意 O(N) 复杂度,能精准就精准。
- 在 Go-Redis 中只需
Do()
调用即可,Pipeline 可批量操作。 - 结合 Lua、RediSearch、NX/XX 等组件,可构建更复杂的布尔状态机和实验平台。
至此,RedisJSON 字符串与布尔操作的核心指令你已全部掌握。下次需要快速翻转开关或标记任务完成,别忘了 JSON.TOGGLE
这把利器!如有问题,欢迎评论交流。