一、我们redis数据库中,事务回事什么样子的呢?
首先我们给出一个定义:redis的事务中,一次执行多条命令,本质是一组命令的集合,一个事务中所有的命令将被序列化,即按顺序执行而不会被其他命令插入
在redis中,事务的作用就是在一个队列中一次性、顺序性、排他性的执行一系列的命令。
事务的生命周期:
1. 事务的创建:使用MULTI开启一个事务
2. 加入队列:在开启事务的时候,每次操作的命令将会被插入到一个队列中,同时这个命令并不会被真的执行
3. EXEC命令进行提交事务
常用的关于事务的命令有:
1. MULTI:使用该命令,标记一个事务块的开始,通常在执行之后会回复OK,(但不一定真的OK),这个时候用户可以输入多个操作来代替逐条操作,redis会将这些操作放入队列中。
2. EXEC:执行这个事务内的所有命令
3. DISCARD:放弃事务,即该事务内的所有命令都将取消
4. WATCH:监控一个或者多个key,如果这些key在提交事务(EXEC)之前被其他用户修改过,那么事务将执行失败,需要重新获取最新数据重头操作(类似于乐观锁)。
5. UNWATCH:取消WATCH命令对多有key的监控,所有监控锁将会被取消。
二、总结redis事务的三条性质:
1. 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断
2. 没有隔离级别的概念:队列中的命令在事务没有被提交之前不会被实际执行
3. 不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制
错误处理
redis的事务没有关系数据库事务提供的回滚功能,
①语法错误。
命令不存在或者参数的个数不对。
例如,跟在multi命令后执行了4个命令,两个是正确的命令,会成功入事务队列,还有两个命令有语法错误。而只要有一个命令有语法错误,执行EXEC命令后Redis就会执行返回错误,连语法正确的命令也不会执行。
127.0.0.1:6379> multi OK 127.0.0.1:6379> set key 1 QUEUED 127.0.0.1:6379> set key (error) ERR wrong number of arguments for 'set' command 127.0.0.1:6379> errorcommand key (error) ERR unknown command 'errorcommand' 127.0.0.1:6379> set key 2 QUEUED 127.0.0.1:6379> exec (error) EXECABORT Transaction discarded because of previous errors.
②运行错误。
执行命令时出现的错误,比如使用散列类型的命令操作集合类型的键,这种错误在实际执行之前redis是无法发现的,所以在事务里这样的命令是会被redis接受并执行的。
如果事务里的一条命令出现了运行错误,其它命令仍然会继续执行,包括出错命令之前和之后的命令。
127.0.0.1:6379> multi OK 127.0.0.1:6379> set key 1 QUEUED 127.0.0.1:6379> sadd key 2 QUEUED 127.0.0.1:6379> set key 3 QUEUED 127.0.0.1:6379> exec 1) OK 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 3) OK 127.0.0.1:6379> get key "3"
开发者必须自己收拾烂摊子,将数据库恢复到事务执行前的状态。因此,与关系数据库的事务相比,redis的事务比较鸡肋。