直接上代码
private final String NO_LOCK_DECRBY_STOCK = " if tonumber(redis.call('get',KEYS[1])) >= math.abs(ARGV[1]) then\n" +
" redis.call('incrby',KEYS[1],ARGV[1])\n" +
" return -1\n" +
" else\n" +
" return -2\n" +
" end";
public Long incrbyStockByLUANoLock(String goodsId, Integer num){
final String stockKey = STOCK_PREFIX + goodsId;
Long l = (Long) this.redisTemplate.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection redisConnection) throws DataAccessException {
Object obj = redisConnection.eval(NO_LOCK_DECRBY_STOCK.getBytes(),
ReturnType.INTEGER, 1,
stockKey.getBytes(),
num.toString().getBytes());
return (Long)obj;
}
});
return l;
}
这里减库存操作用到的是redis的incrby操作,所以库存num为负数,脚本里进行对库存是否足够的判断。
LUA脚本操作具有原子性,且不需要加锁,比在代码里进行逻辑判断,再加锁减库存的性能要高