目录
一 Redis事务-介绍
二 事务的基本操作
三 Redis事务-乐观锁与悲观锁
四 Redis事务-特性
一 Redis事务-介绍
Redis事务可以一次执行多个命令,本质是一组命令的集合,一个事务中的所有命令都会序列化,按顺序的串行化执行,而不会被其他命令插入,不许加塞。
Redis事务有以下三个重要的保证:
1.批量操作在发送EXEC命令前被放入队列缓存
2.收到EXEC命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行
3.在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中,一个事务从开始到执行会经理以下三个阶段:
开始事务
命令入队
执行事务
二 事务的基本操作
#开启事务
multi#执行事务
exec#监控
watch#一旦执行exec,watch监控会被取消127.0.0.1:6379[1]> keys *
(empty array)
127.0.0.1:6379[1]> set k1 100
OK
127.0.0.1:6379[1]> set k2 200
OK
127.0.0.1:6379[1]> set k3 hello
OK
127.0.0.1:6379[1]> get k1
"100"
127.0.0.1:6379[1]> get k2
"200"
127.0.0.1:6379[1]> get k3
"hello"
127.0.0.1:6379[1]>
127.0.0.1:6379[1]>
127.0.0.1:6379[1]> MULTI # 开启事务
OK
127.0.0.1:6379[1](TX)> get k1 # 执行第一条命令
QUEUED
127.0.0.1:6379[1](TX)> get k2 # 执行第二条命令
QUEUED
127.0.0.1:6379[1](TX)> get k3 # 执行第三条命令
QUEUED
127.0.0.1:6379[1](TX)> set k4 300 # 执行第四条命令
QUEUED
127.0.0.1:6379[1](TX)> exec # 执行事务
1) "100"
2) "200"
3) "hello"
4) OK
127.0.0.1:6379[1]>
假如我现在在1号数据库下,我先设置几个值,然后输入命令multi 表示开启事务,此时我get k1 k2 k3 这些命令会被放入队列,我再次set值 ,它也是一个命令,所以会被放入队列。接着,输入命令exec表示执行命令,就会打印出执行命令后的结果!
再来看一下下面这个小例子,体现Redis事务不具有原子性
incr k2可以看作是运行时报错,set k5可以看作是编译时报错
总结:redis的每条命令是原子的,但是redis的事务是不保证原子性的。(MYSQL事务具有原子性)
watch可以监视一个或者多个key,如果在事务执行之前这个(或这些)key被其他命令所改动,那么事务将被打断。
unwatch 取消监视
三 Redis事务-乐观锁与悲观锁
1.悲观锁:顾名思义,就是很悲观,每次去拿数据的时候都会被认为别人会修改,所以每次在拿取数据的时候都会上锁,当其他线程想要访问数据时,都需要阻塞挂起。传统的关系型数据库里边就用到了很多这种机制。比如行锁,表锁,读锁等,都是在操作之前先上锁。
2.乐观锁:【冲突检测和数据更新】
乐观锁,顾名思义,就是很乐观,每次去拿取数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断以下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。
乐观锁策略:提交版本必须大于记录当前版本才能执行更新。一般会使用版本号机制或CSA操作实现。
四 Redis事务-特性
1.单独的隔离操作:事务中所有的命令都会序列化、按序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
2.没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际的执行,也就是不存在“事务内的查询要看到事务里面的更新,在事务外查询不能看到”这个是让人万分头痛的问题。
3.不保证原子性:Redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行。没有回滚。