Redis事务
可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序的串行执行而不会被其他命令插入,不许加塞
事务中的命令是在一个队列中,一次性、顺序性、排他性的执行一系列命令
multi
开启事务,输入的一系列命令redis会将这些命令入队。exec
提交事务Case
Case1
正常执行,可以看到get和set命令都一起入队,最后一期提交执行
127.0.0.1:6379> multi OK 127.0.0.1:6379> set k1 v1 QUEUED 127.0.0.1:6379> get k1 QUEUED 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> EXEC 1) OK 2) "v1" 3) OK
Case2
放弃事务,入队的所有操作将被抛弃
127.0.0.1:6379> multi OK 127.0.0.1:6379> set k1 v1 QUEUED 127.0.0.1:6379> get k1 QUEUED 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> discard OK
Case3
动一发而牵全身
入队时报错那么提交事务时队中的所有命令都将无效
这里是语法错误,根本无法入队。类似于java编译时报错
127.0.0.1:6379> set K1 v1 QUEUED 127.0.0.1:6379> sss k (error) ERR unknown command 'sss' //根本无法入队 127.0.0.1:6379> set a b QUEUED 127.0.0.1:6379> EXEC (error) EXECABORT Transaction discarded because of previous errors.
Case4
可以正常入队,但是提交事务时出错,那么只有出错的那个命令失效
类似于java的运行时错误
127.0.0.1:6379> incr k1 //这里的k1对应的value为v1,虽然能入队但是提交事务时会报错,但其他命令依然能够执行 QUEUED 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> set k3 v3 QUEUED 127.0.0.1:6379> EXEC 1) (error) ERR value is not an integer or out of range 2) OK 3) OK
Case5
watch监控
悲观锁/乐观锁/CAS(Check and Set)
悲观锁:认为错误一定会发生,所以直接上锁。锁住的记录或表不能被其他用户访问
乐观锁:用一个版本号version标记记录,如果提交时发现记录的版本号不一样了就需要重新获取新的记录重新修改(如果版本号高于当前记录版本号那么可以直接修改)
watch a #监视a这个key multi #开启事务 set a b get a append a b #如果在这是另一个用户修改了a这个key的值那么exec将会返回null,表示执行失败 exec (nil)
Redis事务的三特性
单独的隔离操作
事务中的所有命令都会序列化,按顺序的执行。事务在执行过程中不会被其他客户端发送来的命令请求打断
没有隔离级别的概念
队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行,也就不存在 "事务内的查询要看到事务里的更新,在事务外查询不能看到" 这个头疼的问题
不保证原子性
Redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,不会发生回滚