我对Redis事务的理解

在传统关系型数据库中,事务似乎比较好理解,它们也有很明确的特性: ACID。在Redis中,事务的概念似乎没有那么明朗,Redis官方对其定义如下

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

在Redis中,事务是不支持回滚的,同样官方也对其进行了解释,详情见这里

在初学Redis的时候,事务和流水线这两种不同的功能困惑了我很久,从宏观上来看,它们执行方式都相同,都是把一组命令发送到Redis服务器上,然后一条一条顺序执行,那么到底它们有什么区别呢?读了一些专门讲解Redis的书籍才明白: 事务在执行的时候,并不会被别的Redis命令打断,直到事务中所有语句被执行完,其它的Redis命令才能被执行。而流水线只是为了节约几次往返通信的时间,将一组无依赖的命令发送到Redis服务器进行执行,这些命令在执行过程中有可能被其它命令打断。从性能上来讲,流水线是要优于事务的。

MULTIEXECDISCARDWATCHUNWATCH 是 Redis 事务的基础。那么Redis事务具体工作流程是怎么的呢?

简单来讲,客户端是这么使用Redis事务的。首先,客户端执行MULTI命令,代表事务的开启,然后输入一组Redis命令,最后再执行EXEC命令。当Redis从一个客户端那里接收到MULTI命令的时候,它会把之后该客户端发送的所有命令都存储到一个队列里,直到客户端发送EXEC命令,这个时候Redis就会一个一个执行该队列中的命令。

那么WATCHUNWATCHDISCARD又有什么作用呢?通过上一段我们可以知道,在开启MULTI之后,执行EXEC之前,事务中的命令是不会执行的,这段时间可能会有一些键发生变化,比如某个操作导致某个账户对应的余额耗光了,这个时候事务里的操作(如购买商品)应该要失效,这时候就可以用WATCH监控对应的键(账户)是否发生变化,发生变化则不执行事务(体现为抛出WATCHERROR)。而UNWATCH发生在WATCHMULTI之间,它可以对连接进行重置。当买家对一个商品下单之后,如果该商品价格发生了改变,这个时候就可以提前使用UNWATCH取消该事务。同样,DISCARD作用与之相似,在用户使用WATCH监控一个或者多个键并且调用MULTI之后,可以发送DISCARD来取消WATCH命令并清空已入队命令。可见它的发生时机是在MULTIEXEC之间。

目前对Redis事务的理解还比较粗浅,希望以后能有更加深入的理解。


参考

《Redis开发实战》

Redis官方文档