RedisJSON 的 JSON.STRAPPEND字符串追加的正确姿势_json 追加
1 · 写在前面
在数据模型中,“追加”是个高频需求:日志拼接、状态堆栈、消息跟踪……如果把这些信息存在 RedisJSON 文档里,与其整段读出再写回,不如直接用 JSON.STRAPPEND
就地完成。本文将带你从语法、返回值到性能陷阱,全方位掌握 JSON.STRAPPEND
的使用,并配套一段 Go-Redis 代码示例,随取随用。
2 · 指令总览
JSON.STRAPPEND key [path] value
value
追加到指定路径的 JSON 字符串- 插件要求:RedisJSON ≥ 1.0
- ACL 标签:
@json @write @slow
- 默认路径:
$
(根)
3 · 详细语法
JSON.STRAPPEND []
key
path
$
value
字符串写法陷阱
RedisJSON 需要 “字符串的字符串”:
- 直接写
\"hello\"
会被解析成 JSON 字符串 hello- 若它又是数组元素,应再套一层:
\'\"hello\"\'
4 · 返回值解读
执行结果为一个 整数数组,对应每条路径上目标字符串的新长度;若匹配值不是字符串则返回 nil
:
1) (integer) 6 # 路径1 的新长度2) (integer) 8 # 路径2 的新长度3) (nil) # 路径3 不是字符串
5 · 核心示例
5.1 基础追加
redis> JSON.SET doc $ \'{\"a\":\"foo\"}\'OKredis> JSON.STRAPPEND doc $.a \'\"bar\"\'1) (integer) 6redis> JSON.GET doc $.a\"foobar\"
5.2 多路径一次追加
redis> JSON.SET doc $ \'{\"a\":\"foo\",\"nested\":{\"a\":\"hello\"}}\'OKredis> JSON.STRAPPEND doc $..a \'\"baz\"\'1) (integer) 6 # $.a -> foobaz2) (integer) 8 # $.nested.a -> hellobaz
5.3 非字符串路径
redis> JSON.SET doc $ \'{\"num\":123}\'OKredis> JSON.STRAPPEND doc $.num \'\"x\"\'1) (nil) # $.num 不是字符串
6 · 常见踩坑 & 对策
nil
,数据未改变JSON.TYPE
检查或存储时保持类型一致\'\"text\"\'
$..a
通配7 · Go-Redis 实战
// go.mod 需加入: github.com/redis/go-redis/v9package 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()// 初始化文档_, err := rdb.Do(ctx, \"JSON.SET\", \"sess:42\", \"$\", `{\"trace\":\"start\"}`).Result()if err != nil { log.Fatal(err) }// 1️⃣ 追加一段日志res, err := rdb.Do(ctx, \"JSON.STRAPPEND\", \"sess:42\", \"$.trace\", `\"-step1\"`).Slice()if err != nil { log.Fatal(err) }fmt.Println(\"new length:\", res[0]) // (integer)// 2️⃣ 读回验证trace, _ := rdb.Do(ctx, \"JSON.GET\", \"sess:42\", \"$.trace\").Text()fmt.Println(\"trace =\", trace) // \"start-step1\"// 3️⃣ 错误示例:对非字符串追加_, err = rdb.Do(ctx, \"JSON.STRAPPEND\", \"sess:42\", \"$\", `\"-oops\"`).Result()fmt.Println(\"expected err:\", err) // nil,但返回 slice 中含 (nil)}
生产小贴士
- 批量操作时用 Pipeline 减少 RTT。
- 若日志量大可考虑将
trace
切分到数组,用JSON.ARRAPPEND
追加,查询时再STRJOIN
。
8 · 与 JSON.SET/NX/XX 的协同
如果你需要 先写字段(不存在才写),然后持续追加,常见流程是:
JSON.SET key $.log \'\"init\"\' NX
—— 初始化- 若返回
OK
或已存在 JSON.STRAPPEND key $.log \'\"|stepX\"\'
—— 追加
这样可保证字段类型先被固定为字符串,后续 STRAPPEND
不会因为类型错误返回 nil
。
9 · 性能与监控
- 慢日志:JSON 字符串越长,追加越慢;关注
SLOWLOG
超阈值指令。 - 阈值报警:使用
MONITOR
或 Keyspace 通知,当字段长度超过上限及时拆分。 - 内存碎片化:大量追加会导致底层 realloc;可定期对冷数据执行
MEMORY PURGE
(Redis 7.2+)。
10 · 小结
JSON.STRAPPEND
是 RedisJSON原地字符串追加利器,避免全量读写。- 当目标值不是字符串时会静默返回
nil
,务必检查返回数组。 - 复杂路径(如
$..field
)会提升时间复杂度,生产中应尽量 精准定位。 - 在 Go-Redis 中调用
Do()
即可,无需额外封装;并配合 Pipeline 与类型校验写出安全高效的业务代码。
掌握了 JSON.STRAPPEND
,你的 JSON 文档字符串操作将更加优雅、高效。动手试试,把日志、追踪信息或动态状态存进 RedisJSON,感受无需搬数据就能追加的丝滑体验吧!