redis官方文档:Redis transactions
相关命令:
Redis中的事务是一组命令的集合。一个事务中的命令要么都执行,要么都不执行。事务在执行期间,服务器不会中断事务而去执行其它客户端的命令请求,它会将事务中的所有命令都执行完,然后才去处理其它客户端的命令请求。
一、事务的实现
1.multi——开启事务
通过multi命令开启事务,它总是返回OK。MULTI执行之后,客户端可以继续向服务器发送任意多条命令, 这些命令不会立即被执行,而是被放到一个队列中
,当 EXEC命令被调用时, 所有队列中的命令才会被执行。
2.命令入队列
之后所有的命令都会放入事务队列中,并不会立刻执行。
如果客户端发送的命令为EXEC,DISCARD,WATCH,MULTI四个命令中的其中一个,服务器会立刻执行这个命令。
对于这四个命令以外的其它命令,服务器并不会立刻执行,而是将这个命令放入一个事务队列中,然后向客户端返回QUEUED回复。
服务器判断命令是该入队还是该立即执行的过程可以用以下流程图来描述。
事务队列以先进先出(FIFO)的方式保存入队的命令的。
3.exec——执行事务
当客户端向服务器发送EXEC命令时,会立刻执行。
服务器会遍历这个客户端的事务队列,执行队列中保存的所有命令,最后将执行命令所得的结果全部返回给客户端。
4.DISCARD——放弃执行
当执行 DISCARD 命令时, 事务会被放弃, 事务队列会被清空,并且客户端会从事务状态中退出。
5.错误处理
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的事务比较鸡肋。
二、watch命令
watch命令是一个乐观锁,可以为Redis事务提供 check-and-set (CAS)行为。它可以在EXEC命令执行前监视任意数量的键(key),在执行EXEC命令时,检查被监视的键是否已经被修改过,一旦发现被监视的键至少有一个被修改,服务器将拒绝执行事务,并向客户端返回代表事务执行失败的空回复(nil-reply)。
执行EXEC命令后会取消对所有键的监控,如果不想执行事务中的命令可以使用UNWATCH命令来取消监控。