最近项目中有使用到lua脚本使用DECRBY去递减金额,因为计算中的一些不规范使用产生了小数位,导致出现了ERR value is not an integer or out of range,使用的lua脚本如下
local key = KEYS[1]
local decrementValue = tonumber(ARGV[1])
local newValue = redis.call('DECRBY', key, decrementValue)
排查方向
最开始以为是ARGV的值引起来的问题,发现项目中使用了BigDecimal进行金额的处理,但是并没有使用在最后的结果中去掉小数位,以致会出现.00的小数(数据库中的金额是两位小数,但是我们并没有使用小数位,都是整数金额),发现这只是问题的其一。
修改完代码之后,发现写入的key的值是使用jedis.incrByFloat,也会产生小数的问题。
问题处理
- redis的DECRBY命令需要严格使用整数类型,.00这种也是不能使用的,如果使用BigDecimal,需要使用setScale(0)去掉小数位
- 写入的时候value值也不能带小数,最后我的方案是使用jedis.incrBy方法,然后在对value值进行了longValue()进行处理
- 需要注意的是lua脚本中的tonumber只是把传入的字符串转成数字类型,并不会改变小数位