登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

RedisJSON 数组精度选择与内存占用取舍

来源:17golang原创

时间:2026-10-10 19:37:15 272浏览 收藏

RedisJSON 数组的“精度”和“占用”不是同一个开关。少数情况下,把数字改成字符串反而增加管理成本;真正值得先做的是确定误差预算,再决定是否使用 Redis 8.8 的浮点同质数组(FPHA)类型,最后用 JSON.DEBUG MEMORY 测量真实文档。官方入口:https://redis.io/docs/latest/develop/data-types/json/

要点速览
  • 金额、订单号等不可接受误差的值,不要为了省内存直接降成低精度浮点。
  • FPHA 只适合元素类型和精度边界明确的浮点数组,混合整数、字符串或不同结构时不要强行套用。
  • 数组容量、键名和容器开销都会影响结果,估算只能筛选方案,最终要用 JSON.DEBUG MEMORY 实测。

先把精度、格式和内存三个问题拆开

业务里的“精度”至少有三层含义:输入数值能否准确表示,接口返回时是否需要固定小数位,以及 Redis 内部为数组元素和容器分配多少内存。比如传感器温度允许 0.1 的误差,和支付金额必须保留分级单位,选择就不会相同。

Redis JSON 会在解析后以内部结构保存值,内存不等于原始 JSON 字符串长度。数组还有容量和指针等容器开销;官方文档说明容量不足时会按几何方式增长,删除元素也不代表已经分配的容器空间马上归还。因此,先压缩文本、再宣称“内存下降”是不可靠的。

FPHA 怎么选,哪些数组不适合强制指定

Redis 8.8 起,JSON.SET 可对浮点同质数组使用 FPHA BF16|FP16|FP32|FP64。可以把它看成“这个数组里的浮点元素统一采用哪种精度”的存储提示,而不是对任意 JSON 数组的通用压缩按钮。

场景建议原因
模型特征、传感器近似值先评估 FP16/FP32误差可由业务阈值吸收,通常更关注单键规模
计费金额、结算比例保持可审计的整数单位或 FP64不能把舍入误差转嫁给账务
数组包含字符串、整数或嵌套对象不要强制 FPHA它不是同质浮点数组,先调整数据模型
跨版本集群或旧客户端先做兼容性灰度命令选项和返回格式必须由目标版本支持

下面的命令是静态示例,重点是参数关系;注释说明了每一步的目的,输出数值应以目标 Redis 版本的实际结果为准。

# 先写入同质浮点数组,并指定 FP32 作为精度候选
JSON.SET sensor:room:7 $.samples '[21.25,21.50,21.75,22.00]' FPHA FP32
# 读取数组,确认应用看到的值仍满足误差预算
JSON.GET sensor:room:7 $.samples
# 读取 RedisJSON 对该文档的内存估算,不能只看 JSON 文本长度
JSON.DEBUG MEMORY sensor:room:7
RedisJSON 数值数组从业务误差预算到 FP16、FP32、FP64 选择的结构说明图
图1:RedisJSON 数值数组的精度选择结构说明图,不是截图或运行证据。

用实测数据判断内存收益,而不是凭类型名称猜

测试时至少准备三组同样长度的数据:默认数字表示、FP32 和业务允许时的 FP16。每组使用不同的 Redis key,避免覆盖后无法比较;同时记录 key 名长度、数组长度、嵌套层级和读回误差。JSON.DEBUG MEMORY 适合比较相对差异,但官方也提示内存实现会随 Redis 版本改进而变化。

数组从 4 个元素扩到 5 个元素时,容量可能跳到 8;这意味着少量增量会产生阶段性的占用变化。若文档长期追加再删除,容器空间还可能保留。对高频滚动数组,可以采用固定窗口加 JSON.ARRTRIM,或按时间段拆成多个 key;需要彻底收缩时,重建一个新文档通常比反复删除更容易解释。

# 用不同 key 隔离候选方案,避免覆盖导致对比失真
JSON.SET bench:default $ '[1.125,2.250,3.375,4.500]'
JSON.SET bench:fp32 $ '[1.125,2.250,3.375,4.500]' FPHA FP32
# 分别记录两份文档的内部内存,再结合业务误差做决策
JSON.DEBUG MEMORY bench:default
JSON.DEBUG MEMORY bench:fp32
# 只保留窗口内元素;这里的边界是示例,生产值要由采样周期决定
JSON.ARRTRIM bench:fp32 $ 0 1023
RedisJSON 数组容量扩展、JSON.DEBUG MEMORY 测量与拆分策略的关系说明图
图2:数组容量、内存测量与窗口拆分的关系说明图,不是截图或运行证据。

上线前保留三道边界

第一道是数值边界:记录最大绝对值、最小步长和允许误差,任何低精度选择都必须能回到这张表。第二道是版本边界:确认所有节点支持 FPHA,客户端不会把返回值误判为字符串或整数。第三道是容量边界:用生产形状的数据测量单键、批量读取和数组增长后的内存,而不是只测一个四元素样例。

如果数组需要精确检索、频繁局部更新或与 JSONPath 查询强绑定,RedisJSON 的结构优势更明显;如果只是连续数值流并且主要按时间范围读写,也应把 RedisJSON 与专用时序结构做一次成本比较。精度降低只有在误差可解释、回滚可执行、监控能发现异常时才值得。

常见问题

FP16 一定比 FP32 更省内存吗?

不应只看元素宽度。数组容量、文档结构、键名和版本实现都会影响总量,必须用相同数据形状的 JSON.DEBUG MEMORY 对比。

删除数组元素后内存会立刻下降吗?

不一定。容器已经分配的容量可能保留;如果长期增长和删除造成浪费,可采用固定窗口或重建文档。

金额数组可以直接使用 FPHA 吗?

除非完成误差和审计评估,否则不建议。金额更适合使用最小货币单位整数,或选择能满足精度要求的表示方式。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>