Redis的事务处理

发表时间:2017-07-19 21:51:06 浏览量( 19 ) 留言数( 0 )

学习目标:

1、了解Redis的事务的特性

2、了解Redis的事务的使用


学习过程:

    事务的原理是先将属于一个事务的命令发送给redis ,然后再让 redis 依次执行这些命令,在redis中,事务的作用就是在一个队列中一次性、顺序性、排他性的执行一系列的命令。


事务的生命周期:

  • 事务的创建:使用MULTI开启一个事务

  • 加入队列:在开启事务的时候,每次操作的命令将会被插入到一个队列中,同时这个命令并不会被真的执行

  • EXEC命令进行提交事务, DISCARD:放弃事务,即该事务内的所有命令都将取消


常用的关于事务的命令有:

  • MULTI:使用该命令,标记一个事务块的开始,通常在执行之后会回复OK,(但不一定真的OK),这个时候用户可以输入多个操作来代替逐条操作,redis会将这些操作放入队列中。

  • EXEC:执行这个事务内的所有命令

  • DISCARD:放弃事务,即该事务内的所有命令都将取消

  • WATCH:监控一个或者多个key,如果这些key在提交事务(EXEC)之前被其他用户修改过,那么事务将执行失败,需要重新获取最新数据重头操作(类似于乐观锁)。

  • UNWATCH:取消WATCH命令对多有key的监控,所有监控锁将会被取消。  

1、基本使用

示例代码:

执行事务

127.0.0.1:6379> multi

OK

127.0.0.1:6379> set key1 one

QUEUED

127.0.0.1:6379> INCR num1

QUEUED

127.0.0.1:6379> INCR num1

QUEUED

127.0.0.1:6379> set key2 two

QUEUED

127.0.0.1:6379> exec

1) OK

2) (integer) 1

3) (integer) 2

4) OK

127.0.0.1:6379> get num1

"2"

放弃事务示例:

当执行 DISCARD 命令时, 事务会被放弃, 事务队列会被清空, 并且客户端会从事务状态中退出:

> SET foo 1

OK

> MULTI

OK

> INCR foo

QUEUED

> DISCARD

OK

> GET foo

"1"


2、隔离测试,watch使用

  隔离性需要和watch结合使用,redis不支持脏数据等级别的。 我们可以开启两个客户端,在exec之前,由另外一个客户端修改,看一下结果

第一个客户端

127.0.0.1:6379> watch num1

OK

127.0.0.1:6379> multi

OK

127.0.0.1:6379> INCR num1

QUEUED


第二个客户端修改num1的值

[root@run1 bin]# ./redis-cli 

127.0.0.1:6379> INCR num1

(integer) 214


第一个客户端执行事务

127.0.0.1:6379> exec

(nil)

127.0.0.1:6379> unwatch

OK

可以看到事务执行失败了。



3、不保证原子性的测试

看一下下面的例子,第二个执行虽然错误了,但是其他的命令都还是可以执行成功的。

127.0.0.1:6379> multi 

OK

127.0.0.1:6379> set name liubao

QUEUED

127.0.0.1:6379> incr name

QUEUED

127.0.0.1:6379> incr num1

QUEUED

127.0.0.1:6379> incr num1

QUEUED

127.0.0.1:6379> exec

1) OK

2) (error) ERR value is not an integer or out of range

3) (integer) 211

4) (integer) 212

127.0.0.1:6379> get num1

"212"


但是如果入队的时候就发生了错误,那么所有的都不会执行的

127.0.0.1:6379> multi 

OK

127.0.0.1:6379> incr num1

QUEUED

127.0.0.1:6379> abc

(error) ERR unknown command 'abc'

127.0.0.1:6379> exec

(error) EXECABORT Transaction discarded because of previous errors.

127.0.0.1:6379> get num1

"212"


    总的来说redis事务的特点:Redis 事务可以做到保证一致性(C)和隔离性(I),但并不保证原子性(A)和持久性(D)。

  • 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断

  • 没有隔离级别的概念:队列中的命令在事务没有被提交之前不会被实际执行

  • 不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制