Redis HINCRBY覆盖重新锁定的事务中的数据

时间:2018-11-28 19:03:27

标签: node.js redis transactions

我有一个可以将用户余额更新一定量的功能:

export function incrementUsersOpenOrderBalance(order, amount, multi) {
  multi.hincrby('order_sums', `${order.GetUserId()}-${order.coin}`, amount)
}

在99%的时间内都能正常运行。它在一个redlock中:

    try {
      lock = await rateLock.lock(`locks:balance:${userId}`, 60000)
      let userBalance = await balancestore.getBalanceForUserId(userId)
      do {
        let multi = redis.multi();
        executedTrades = await placeOrder(orderProcessing, userBalance, multi)
        await completeTradesInTransaction(executedTrades, execMulti)
      } while (1);
    } catch(e) {
       ...
    } finally {
      if (lock) {
        lock.unlock()
        lock = null
      }
    }

execMulti)正在呼叫await multi.execAsync()

内部有很多逻辑,但是每个呼叫仅更新一次用户平衡。由于某些原因,它有时不会HINCRBY -XXXXXXX并减少正确的数量。我注意到趋势每发生一次,它实际上就会运行此HINCRBY -XXXXXXX命令,然后进行下一个订单处理,然后实际上会将用户余额设置为-XXXXXXX。我猜想它发生在HINCRBY -XXXXXXX调用期间,实际上它覆盖了值而不是更新它。

我已经跑过redis-cli MONITOR了几次,奇怪的是我觉得一切都很好。

1543351721.451263 [0 lua] "set" "locks:balance:userid" "random_value" "NX" "PX" "60000"
1543351721.473371 [0 10.56.5.109:47958] "multi"
1543351721.473533 [0 10.56.5.109:47958] "hincrby" "order_sums" "userid" "-2483395200000"
1543351721.473598 [0 10.56.5.109:47958] "hincrby" "sums" "order-sum" "-3520000"
1543351721.473635 [0 10.56.5.109:47958] "exec"
1543351721.483502 [0 lua] "get" "locks:balance:userid"
1543351721.483543 [0 lua] "del" "locks:balance:userid"
1543351721.485265 [0 lua] "set" "locks:balance:userid" "new_random_value" "NX" "PX" "60000"
1543351721.501101 [0 10.56.5.109:47958] "multi"
1543351721.501331 [0 10.56.5.109:47958] "hincrby" "sums" "order_sum" "-3910000"
1543351721.501376 [0 10.56.5.109:47958] "hincrby" "order_sums" "userid" "-2758544100000"
1543351721.501507 [0 10.56.5.109:47958] "exec"
1543351721.503079 [0 lua] "get" "locks:balance:userid"
1543351721.503104 [0 lua] "del" "locks:balance:userid"

如您所见,它每次都会锁定,然后以MULTI开始事务,执行hincrby,然后是EXEC,然后释放锁定。

此后,我将其发布余额,并将userid余额设置为-2483395200000。我已经多次注意到这种行为。

基本上HINCRBY很少覆盖数据而不是更新数据。

0 个答案:

没有答案