Redis HMSET存储长JSON字符串时json_content字段返回nil问题
故障原因
json_content字段查询返回nil,核心原因是特殊字符未转义+命令参数解析失败,具体触发逻辑:
- Redis执行命令时以空格、未转义双引号作为参数分隔符,写入的JSON串包含大量未转义的双引号、反斜杠、HTML属性字符,Redis无法识别完整JSON为
json_content对应的value值,命令实际执行时会抛出参数数量错误,若客户端未捕获异常就会表现为字段写入失败,查询返回nil。 - 示例中给出的JSON片段本身存在结构截断问题:
NextEra Energy...........后直接拼接"section_28",缺失p标签闭合、字段值闭合引号和对象分隔逗号,即使转义正确,本身也不是合法JSON结构。 - 多次调用
HMSET写入同一个hash key的操作本身没有语法问题,前两个字段因为值是纯数字,没有特殊字符,所以能正常写入。
修复方案
优先使用客户端原生API写入,禁止手动拼接命令字符串
所有编程语言的标准Redis客户端都内置了RESP协议序列化逻辑,调用hset/hmset方法时直接传入从Oracle CLOB读取转换后的完整JSON字符串作为参数即可,客户端会自动完成所有特殊字符转义,完全不需要手动处理,这是生产环境唯一推荐的方案。以Java Jedis客户端为例:
// 从Oracle CLOB字段读取内容转为字符串后直接传入,不要手动拼接命令文本 try (Jedis jedis = pool.getResource()) { jedis.hset("279479", "json_content", clobToString(clobContent)); }
手动拼接命令字符串的方式在遇到特殊字符、超长文本时几乎必然出现转义问题,生产环境禁止使用。
调试场景手动执行命令的转义规则
如果需要在redis-cli中调试手动写入,必须做两层处理:
- 补全JSON的完整合法结构,闭合所有标签、引号和对象分隔符
- 给整个JSON值外层加双引号包裹,将JSON内部的所有双引号前加反斜杠转义,JSON内部原有的反斜杠需要再加一层反斜杠转义
正确的写入示例:
HMSET 279479 json_content "{\"section_1\":{\"section_publish\":true,\"section_body\":\"<p style=\\\"text-align: justify;\\\">NextEra Energy 示例内容</p>\"},\"section_28\":{\"section_publish\":true,\"section_body\":\"\"},\"section_29\":{\"section_publish\":true,\"section_body\":\"\"}}"
大CLOB内容存储优化
- 如果从Oracle导出的CLOB单条内容超过10KB,建议先做gzip压缩再存入Redis,降低内存占用和网络传输开销
- 如果单条内容超过500MB,不建议存入Redis,避免大value阻塞Redis主线程影响服务可用性
内容的提问来源于stack exchange,提问作者Landon Statis
相关产品推荐
相关产品推荐

