前两篇 Redis 文章都大几千字,今天咱们换个小清新点的,篇幅很少也容易理解。redis
若是你也了解过关系型数据库事务的话,相信这篇文章对你来讲是很容易理解的了。具体什么是事务我就不说很少了,直接讲 Redis 事务相关的部分。数据库
首先,咱们先来看下,Redis 是怎么执行事务的。编程
show code:设计模式
127.0.0.1:6379> multi OK 127.0.0.1:6379> set a test1 QUEUED 127.0.0.1:6379> set b test2 QUEUED 127.0.0.1:6379> exec 1) OK 2) OK 127.0.0.1:6379> get a "test1" 127.0.0.1:6379> get b "test2"
一个事务的开始到结束会通过如下 3 个过程微信
结合上面的例子,用人话介绍这 3 个过程就是:数据结构
Redis 执行 multi 命令标志事务开始。架构
当客户端切换至事务状态后,服务端会将除了 exec、discard(取消事务,放弃执行事务块内的全部命令)、watch 和 multi 之外的命令放进一个先进先出的事务队列中。即上面例子的 2 个 set 命令会被放进队列,并返回 QUEUED 给客户端。spa
当客户端发送 exec 命令时,服务端会当即执行该命令。遍历这个客户端的事务队列,执行队列保存的全部命令。最后将执行命令所得结果返回给客户端。设计
二者最大区别就是 Redis 事务不支持回滚。即便事务队列中某个命令在执行期间发生了错误,事务也会继续执行,直到事务队列中全部命令执行完成。code
文字貌似不够直观,没事,看下面的例子你就立刻明白了。
127.0.0.1:6379> multi OK 127.0.0.1:6379> set msg test QUEUED 127.0.0.1:6379> lpop msg QUEUED 127.0.0.1:6379> exec 1) OK 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 127.0.0.1:6379> get msg "test" // 不受后面错误命令影响
PS:若是客户端向事务入列一个错误的命令(好比输入一个不存在的命令,像:sett 命令),那么该事务将不被服务端执行。该状况是入队错误,上面例子是执行错误的状况。
提到 redis 事务,就不得不提 watch 命令了。
该命令是一个乐观锁,只能在客户端进入事务状态以前执行。
做用是 exec 命令执行以前,监视任何数量个键,并在 exec 命令执行时,检查被监视的键是否至少有一个已经被修改过。如果则拒绝执行事务,不然执行。
当 exec 执行完成后,此次事务也就结束了。
咱们依旧来看一个简单的栗子:
127.0.0.1:6379> SET msg test //设置 msg 的值 OK 127.0.0.1:6379> WATCH msg //监视 msg OK 127.0.0.1:6379> SET msg test2 //修改 msg 的值(或其余客户端在该客户端执行 exec 命令以前修改该值) OK 127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SET msg test3 QUEUED 127.0.0.1:6379> GET msg QUEUED 127.0.0.1:6379> EXEC (nil) //执行失败
PS:本文原创发布于微信公众号「不仅Java」,坚持原创!后台回复如下关键字获取经典必读书籍:Java、MySQL、Redis、Linux、mq、数据结构、设计模式、编程思想、架构