MST

星途 面试题库

面试题:Redis事务在账户余额更新中如何实现基本的一致性保证

在使用Redis进行账户余额更新场景下,简单描述Redis事务的一般流程,以及如何通过事务来确保账户余额更新操作的一致性,例如在扣减和增加余额时,如何防止并发问题导致数据不一致?
46.9万 热度难度
数据库Redis

知识考点

AI 面试

面试题答案

一键面试

Redis事务一般流程

  1. 开启事务:使用 MULTI 命令,该命令会将后续的命令放入队列中,而不是立即执行。
  2. 命令入队:在开启事务后,可以依次发送需要执行的命令,如 INCRDECR 等,这些命令会被加入到事务队列中暂存。
  3. 执行事务:使用 EXEC 命令,Redis 会按顺序执行事务队列中的所有命令,并将结果返回。如果在执行 EXEC 之前使用 DISCARD 命令,则会取消事务,清空事务队列。

确保账户余额更新操作一致性及防止并发问题

  1. 使用事务:在扣减和增加余额操作时,将这些操作放在一个事务中。例如,扣减余额的命令 DECRBY key amount 和增加余额的命令 INCRBY key amount 都放在 MULTIEXEC 之间。这样能保证这两个操作要么都执行成功,要么都不执行,不会出现部分成功的情况。
  2. 乐观锁机制:可以结合 WATCH 命令实现乐观锁。在开启事务前,使用 WATCH key 命令来监控账户余额对应的键。如果在 WATCH 之后,EXEC 之前,该键的值被其他客户端修改,那么当前事务会执行失败,返回 (nil)。客户端可以捕获这个返回值,重新获取最新的余额,再次尝试执行事务。示例代码如下(以Python Redis 客户端为例):
import redis

r = redis.Redis(host='localhost', port=6379, db=0)

while True:
    try:
        pipe = r.pipeline()
        balance = r.get('account_balance')
        if balance is None:
            balance = 0
        else:
            balance = int(balance)
        pipe.watch('account_balance')
        new_balance = balance - 10  # 扣减10
        pipe.multi()
        pipe.set('account_balance', new_balance)
        pipe.execute()
        break
    except redis.WatchError:
        continue

通过这种方式,在并发环境下,能有效防止数据不一致问题,确保账户余额更新操作的一致性。