redis的事务(简单介绍)

1、简单描述

   redis对事务的支持目前还是比较简单。redis只能保证一个client发起的事务中的命令是可以连续的执行,而中间不会插入其他client的命令。由于redis是但现场来处理所有client的请求的,所以这种事务的实现还是容易的。

 

2、相关操作

1)mulit命令:发起事务。

2)exec命令:收到此命令后,redis会执行client开启事务后发来的一连串的命令,并返回所有命令的执行结果。

  一般来说,redis接收到client发来的命令后是马上处理并返回结果,但是当接收到multi命令时,redis会让这个client的连接进入一个事务的上下文,该连接发来的后续命令并不是立即执行,而是放到队列里面,直到收到exec命令就开始执行队列中的命令,执行完后把结果发给client,然后此连接就关闭事务上下文。

3)discard命令:取消事务处理。比如multi命令发出后,操作了一些命令,在执行exec前遇到问题想退出事务,可以用这个discard命令,那么multi发起之后的所有命令都不会被执行。队列会被清空掉,事务上下文也会关闭。

 【注意】multi之后的多个命令,如果有命令执行的结果是出错的,不影响后续的命令的执行。

 【注意】上面截图的列子可以看到事务中有命令操作失败的,但是没有回滚,这是redis事务的一个缺陷。

4)乐观锁(watch命令)

  在事务执行前可以先watch一些key,如果这些key的值没有变化,那么可以执行mulit的命令,如果有变化,则事务会退出,exec操作会返回nil。

【注意】watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被清空。exec和discard以及unwatch都可以清除连接中的监视。

 

3、小结

1)虽说redis事务在本质上也相当于序列化隔离级别的了,但是由于事务上下文的命令只排队并不会立即执行,所以事务中的写操作不能依赖事务中的读操作结果;

2)在php中可以使用phpredis扩展。如果使用了multi,代码中不能够对之后的命令比如 get命令的结果进行处理,因为get命令会返回一个句柄,而不是返回get到的key的值,因为multi之后的命令会被放在队列中。

3)事务是没有回滚功能,部分命令执行失败,不影响其他的命令。

4)如果事务操作过程中,redis挂了,会导致部分操作成功,部分失败。如果用aof方式做持久化,redis会用write操作写入整个事务内容,但是这样还是有可能只有一部分的事务写入了磁盘,redis重启的时候检测到这种情况,然后失败退出。要使用redis-check-aof工具来修复,会删除写入的这部分的事务,然后重启才能成功。

 

posted @ 2017-08-28 16:56  汤姆雷特  阅读(280)  评论(0编辑  收藏  举报