使用ParseObject.increment()函数时如何处理浮点算术精度问题
Parse平台increment操作浮点精度问题官方处理方案
Parse官方针对increment原子操作的浮点精度误差问题,推荐两种不破坏原子性、无竞态风险的处理方案:
首选方案:整数放大存储法
从根源规避浮点运算误差,是官方首推的最优方案:
- 按照业务所需的数值精度,将浮点值放大为整数存储,比如需要保留2位小数就统一乘以100,例如6.5存储为650,增量-4.1转换为-410
- 调用
increment方法时直接传入放大后的整数值:myobject.increment("Quantity", -410) - 从数据库读取数值后,除以对应的放大倍数即可得到业务所需的浮点值
该方案全程使用整数运算,完全不会出现浮点精度问题,同时完整保留了increment的原子性,支持高并发场景下的并发修改,性能也最好,适合库存、金额、计量值等所有固定精度的数值场景。
备选方案:云代码beforeSave钩子统一修正
如果存量业务无法修改存储结构,可以使用Parse云代码的beforeSave钩子在数据落库前做统一精度修正:
- 只针对目标浮点字段做舍入处理,不会影响其他字段的正常写入,参考代码如下:
Parse.Cloud.beforeSave('你的业务类名', (request) => { const quantity = request.object.get('Quantity'); // 仅当Quantity字段有变更时才执行修正 if (quantity !== undefined && request.object.dirty('Quantity')) { // 按业务需要的小数位调整,示例为保留2位小数 const roundedVal = Math.round(quantity * 100) / 100; request.object.set('Quantity', roundedVal); } });
- 修正逻辑在服务端写入事务中执行,不会破坏
increment的原子性,依然可以避免竞态问题。
不推荐的操作
不要采用「客户端先读取当前值→本地计算→赋值回写」的方式,该方式会丢失increment的原子性,高并发场景下必然出现数据覆盖的错误。
内容的提问来源于stack exchange,提问作者switch201
相关产品推荐
相关产品推荐

