> 技术文档 > RedisJSON 指令精讲JSON.STRLEN 高效统计字符串长度

RedisJSON 指令精讲JSON.STRLEN 高效统计字符串长度


1 · 场景与价值

在日志累加、指标采集、消息追踪等场景中,我们常需快速判断某个字符串字段“到底有多长”,以便:

  • 阻止过大日志:若长度超限则截断或归档;
  • 动态分桶:按长度选择不同存储策略;
  • 性能监控:突然飙长可能暗示异常循环或恶意输入。

有了 JSON.STRLEN,无需把整段内容取回客户端,也无需额外存副本,即可 O(1) 地获取字段长度。

2 · 指令概览

指令 作用 复杂度 JSON.STRLEN key [path] 返回指定路径 JSON 字符串的长度 O(1)(单路径) / O(N)(多路径,与键大小相关)
  • 可用版本:RedisJSON ≥ 1.0
  • ACL 标签@json @read @slow
  • 默认路径$(根)

3 · 语法参数

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

返回值

  • 若匹配为字符串:返回其长度(整型)。
  • 若路径不存在 / 类型非字符串:返回 nil
  • 多路径:递归数组,顺序对应各匹配点。

4 · 基本示例

redis> JSON.SET doc $ \'{\"a\":\"foo\",\"nested\":{\"a\":\"hello\"},\"nested2\":{\"a\":31}}\'OK# 多路径统计redis> JSON.STRLEN doc $..a1) (integer) 3 # $.a -> \"foo\"2) (integer) 5 # $.nested.a -> \"hello\"3) (nil)  # $.nested2.a 不是字符串

5 · 常见用法场景

5.1 日志超长保护

> len=$(redis-cli JSON.STRLEN log:123 $.trace)> if [ \"$len\" -gt 2048 ]; then> redis-cli JSON.SET log:123 $.trace \'\"\"\'> fi

5.2 统计动态字段占用

# 查看所有用户简介 bio 的平均长度redis-cli --raw KEYS \"user:*\" | while read k; do redis-cli JSON.STRLEN $k $.biodone | awk \'{s+=$1;c++} END{print s/c}\'

6 · 踩坑与注意

坑 症状 解决方案 路径非字符串 返回 nil,误以为不存在 先 JSON.TYPE 或保证字段类型一致 多路径扫描过大文档 延迟抖动 精准路径,避免 $..field 空键 / 空路径 直接 nil 先用 EXISTSJSON.TYPE 判断 把数组当字符串 长度不是元素数 STRLEN 只算字节数,不是元素数,数组用 JSON.ARRLEN

7 · Go-Redis 完整示例

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()// 初始化测试文档_, err := rdb.Do(ctx, \"JSON.SET\", \"msg:1\", \"$\",`{\"body\":\"hello world\",\"meta\":{\"note\":\"short\"}}`).Result()if err != nil { log.Fatal(err) }// 1️⃣ 单路径长度len1, _ := rdb.Do(ctx, \"JSON.STRLEN\", \"msg:1\", \"$.body\").Int64()fmt.Println(\"body len =\", len1) // 11// 2️⃣ 多路径长度res, _ := rdb.Do(ctx, \"JSON.STRLEN\", \"msg:1\", \"$..note\").Slice()fmt.Println(\"meta.note len =\", res[0]) // 5// 3️⃣ 类型不符示例_, _ = rdb.Do(ctx, \"JSON.SET\", \"msg:1\", \"$.count\", 100)res2, _ := rdb.Do(ctx, \"JSON.STRLEN\", \"msg:1\", \"$.count\").Slice()fmt.Printf(\"count -> %#v\\n\", res2[0]) // }

8 · 性能建议

  1. 批量调用使用 Pipeline

    pipe := rdb.Pipeline()keys := []string{\"user:1\", \"user:2\", \"user:3\"}for _, k := range keys { pipe.Do(ctx, \"JSON.STRLEN\", k, \"$.bio\")}_, _ = pipe.Exec(ctx)
  2. 监控慢查询
    复杂 JSON + 多路径 ($..field) 会触发 SLOWLOG,需关注。

  3. 字符串膨胀预警
    可用 MEMORY USAGE key + JSON.STRLEN 建立长度阈值报警。

9 · 与其它指令的协同

需求 组合 说明 追加后检测 JSON.STRAPPENDJSON.STRLEN 先写后查,防止长度爆表 长度分片 JSON.STRLEN + JSON.SET 达阈值切换到新字段 类型校验 JSON.TYPE + JSON.STRLEN 防止对非字符串统计

10 · 总结

  • JSON.STRLEN 提供 O(1) 字段级长度统计,是日志与配额场景的利器。
  • 返回值为整型或 nil,多路径时请按序处理。
  • 精准路径 ≫ 通配路径,能显著降低 O(N) 扫描成本。
  • 在 Go-Redis 中用 Do() 一行即可调用,并能与 Pipeline/事务无缝整合。

至此,字符串家族三兄弟 STRLEN / STRAPPEND / SET 已全部集齐。灵活运用它们,你的 RedisJSON 文档读写将更加高效、细粒度且安全。祝编码愉快,欢迎留言交流实践体会!

全民K歌电脑版