> 技术文档 > RedisJSON 指令精讲JSON.TOGGLE 键翻转布尔值

RedisJSON 指令精讲JSON.TOGGLE 键翻转布尔值


1 · 为什么要学 JSON.TOGGLE?

在特性开关、状态机、AB 实验、勾选框等场景下,我们经常需要把 truefalse 来回切换。传统做法要先 JSON.GET 读出布尔值、在客户端翻转、再 JSON.SET 写回;这不仅多一次 RTT,还增加竞态风险。JSON.TOGGLE 直接在 Redis 端 原子翻转 布尔字段,让代码更简洁、操作更安全。

2 · 指令概览

指令 作用 复杂度 JSON.TOGGLE key [path] 将指定路径布尔值取反 O(1)(单路径) / O(N)(多路径,与键大小相关)
  • 可用版本:RedisJSON ≥ 2.0.0
  • ACL 标签@json @write @slow
  • 默认路径$(根)

3 · 语法解析

JSON.TOGGLE  []
参数 必填 说明 key ✔ 目标键名 path JSONPath,省略时为 $

返回值

  • 布尔 → 数字:翻转后值,1 代表 true0 代表 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 · 典型使用场景

场景 描述 建议组合 特性开关 (Feature Toggle) 打开 / 关闭实验功能 JSON.MGET 批量查开关 + JSON.TOGGLE 动态翻转 任务完成标记 任务完成后置 donetrue 失败重试时再次 TOGGLE 复位 二元状态机 资源占用 (locked) 字段 true/false 配合 WATCH 做乐观锁 反向 AB 实验 随机翻转用户 groupA 字段做对照 批量脚本调用 JSON.TOGGLE

6 · 踩坑与注意

坑 现象 对策 字段类型不是布尔 返回 nil,值不变 初始化时固定字段类型;或先 JSON.TYPE 校验 多路径扫描大文档 时间复杂度 O(N) 避免 $..flag 通配,改用精确路径 版本兼容 RedisJSON 1.x 无此指令 部署前确认插件版本≥2.0 误操作连续翻转 状态乱跳 搭配 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 · 性能与并发建议

  1. 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
  2. 慢日志监控

    • 大文档 + 多路径 ($..flag) 易触发 SLOWLOG
  3. 幂等 API

    • Web 接口里应返回翻转后值,而不是固定 200 来避免并发写乱序。

9 · 与其他指令的协同

目标 指令组合 说明 首次写布尔 + 后续翻转 JSON.SET ... NXJSON.TOGGLE 先用 NX 保证类型,后续直接翻转 布尔统计 FT.AGGREGATE + JSON.TOGGLE RediSearch 聚合统计 true/false 数量 布尔值批量置位 JSON.SET + JSON.TOGGLE 批量清零后一键启用

10 · 小结

  • JSON.TOGGLE 为布尔字段提供了 原子取反 能力,消除读-改-写竞态。
  • 返回值 1 / 0 表示翻转后的 true / false,可直接用作状态。
  • 多路径场景要注意 O(N) 复杂度,能精准就精准。
  • 在 Go-Redis 中只需 Do() 调用即可,Pipeline 可批量操作。
  • 结合 Lua、RediSearch、NX/XX 等组件,可构建更复杂的布尔状态机和实验平台。

至此,RedisJSON 字符串与布尔操作的核心指令你已全部掌握。下次需要快速翻转开关或标记任务完成,别忘了 JSON.TOGGLE 这把利器!如有问题,欢迎评论交流。