(一).介绍Redis事务
在前面介绍Mysql的时候也介绍到过事务的概念,例如ACID特性。但是Redis的事务相对于Mysql的事务来说,是比较简单的。
"原子性":只做到了把多个包打包在一起,要么全都执行,要么全都不执行,不保证成功,如果事务中有若干个操作,存在有失败的,也不会进行回滚操作
"一致性":不具备一致性。Redis没有约束,也没有回滚操作。事务执行过程中如果某个修改操作出现失败,就可能会导致不一致的情况。
"持久性":不具备持久性。Redis为内存数据库,数据是存储在内存中的。虽然有持久化机制,但是和事务没有任何关系。
"隔离性":不涉及隔离性。Redis是一个单线程模型的服务器程序,所有的请求都是"串行"执行的。
Redis事务的存在意义在于**"打包",避免其他客户端的命令插队到中间** 。Redis在底层实现事务,是引入了一个队列,每次客户端在事务中进行一个操作,都会把命令先发给服务器,放到队列中,但是并不会执行 ,而是只有当真正受到执行事务的命令后,才会执行队列中的所有操作。
之前在介绍多线程的时候,我们是通过"加锁"的方式来避免"插队",在Redis中可以直接使用事务
(二).关于事务的操作
1.MULTI
MULTI,开启事务执行完成后,返回OK

由于现在并没有执行事务,所以通过另一个客户端访问是访问不到的,目前只是在服务器的事务队列中,保存了上述的请求

可以看到,我们是访问不到的
2.EXEC
EXEC,执行事务

当我执行事务之后,再获取

可以看到,是可以获取到的
3.DISCARD
放弃当前事务,此时直接清空事务队列,之前的操作都不会真正的执行到。

如果在事务中发生了服务器重启操作,那么就相当于discard。
4.WATCH
在执行事务的时候,如果某个事务修改的key值,被其他客户端修改了,此时就容易出现数据不一致的问题,WATCH命令就是用来监控具体的key的,看看这个服key在事务的multi和exec之间,set key之后是否在外部被其他客户端修改了
我们通过一个案例来看

当我们执行之后,看一看key的值是多少】
客户端1开启事务,并设置key

客户端2直接设置key

客户端1执行事务

当获取key的之后

发现key的结果是111
这是因为,虽然客户端1设置了key,但是并没有执行事务,也就是说,这个key一直在事务队列中并没有执行。然后执行事务的操作是在客户端设置key之后执行的,所以最终的key的值是客户端1的值。
此时,站在客户端2的角度,就发生了"数据不一致"问题。
为了解决这个问题,我们可以通过WATCH命令来解决这个问题

客户端1

客户端2

当客户端1提交事务的时候,发现提交不了

这就是WATCH的功劳
WATCH,当开启事务的时候,对watch的key进行修改,此时就会记录当前key的**"版本号"** (版本号是一个整数,每次修改都会使版本变大,服务器来维护每个key的版本号情况)。当真正提交事务的时候,如果发现当前服务器上的key的版本号已经超过了事务开始时的版本号,此时就会让事务执行失败。
