在《买一单送一单!原来是并发扣款惹的祸...》一文里,我们使用CAS乐观锁,可以在不影响吞吐量的前提下,保证余额的一致性。
之前的场景,余额是保存在MySQL中。如果余额是放到redis里(例如:秒杀等业务场景),又该怎么做呢?
如果余额是放在redis里,那么需要扣减余额的业务方执行:
$money = GET key
执行业务计算,得出新的余额
SET key $new_money
在并发量大的时候,一样会遇到前文描述的一致性问题。
Redis如何实现事务性?
Redis的 WATCH 和 EXEC 可以提供类似事务的机制:
- WATCH观察key是否被改动
- 如果提交时key被改动,EXEC将返回null,表示事务失败
保证一致性的余额扣减可能类似于这样执行:
WATCH key
$money = GET key
执行业务计算,计算出新的余额
MULTI
SET key $new_money
EXEC
在WATCH之后,EXEC执行之前,如果key的值发生变化,则EXEC会失败。可以看出,redis的事务本质上就是乐观锁CAS机制。
关注【老张聊架构】,前迅雷大数据CTO带你成为百万年薪架构师!