У меня есть функция, которая обновляет баланс пользователя на определенную величину:
export function incrementUsersOpenOrderBalance(order, amount, multi) {
multi.hincrby('order_sums', `${order.GetUserId()}-${order.coin}`, amount)
}
, которая отлично работает в 99% случаев.Он находится внутри блокировки:
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
очень редко перезаписывает данные вместо того, чтобы обновлять их.