面试题答案
一键面试Redis事务一般流程
- 开启事务:使用
MULTI
命令,该命令会将后续的命令放入队列中,而不是立即执行。 - 命令入队:在开启事务后,可以依次发送需要执行的命令,如
INCR
、DECR
等,这些命令会被加入到事务队列中暂存。 - 执行事务:使用
EXEC
命令,Redis 会按顺序执行事务队列中的所有命令,并将结果返回。如果在执行EXEC
之前使用DISCARD
命令,则会取消事务,清空事务队列。
确保账户余额更新操作一致性及防止并发问题
- 使用事务:在扣减和增加余额操作时,将这些操作放在一个事务中。例如,扣减余额的命令
DECRBY key amount
和增加余额的命令INCRBY key amount
都放在MULTI
和EXEC
之间。这样能保证这两个操作要么都执行成功,要么都不执行,不会出现部分成功的情况。 - 乐观锁机制:可以结合
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
通过这种方式,在并发环境下,能有效防止数据不一致问题,确保账户余额更新操作的一致性。