Redis的事务
redis的事务可以一次执行多个命令, 并且带有以下两个重要的保证:
一、事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
二、事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
当使用AOF方式做持久化的时候,Redis会使用单个write(2)命令将事务写入到磁盘中。如果Redis服务器因为某些原因被管理员杀死,或者遇上某种硬件故障,那么可能只有部分事务命令会被成功写入到磁盘中。Redis在重新启动时发现AOF文件出了这样的问题,那么它会退出,并汇报一个错误。使用redis-check-aof程序可以修复这一问题:它会移除 AOF 文件中不完整事务的信息,确保服务器可以顺利启动。
事务命令
multi
用于开启一个事务 开启事务之后客户端可以继续向服务器发送任意多条命令,这些命令不会立即被执行,而是会按照先后顺序被放到一个队列中,最后由exec命令原子性(atomic)地执行 事务内传入的命令都会返回一个内容为QUEUED的状态回复,表示添加到队列当中 总是返回OK
watch key [key...]
监视一个(或多个)key 如果在事务执行之前这些key被其他命令改动,那么事务将被打断 如果使用watch监视了一个带过期时间的键,那么即使这个键过期了,事务仍然可以正常执行 当客户端断开连接时, 该客户端对键的监视也会被取消 总是返回OK
unwatch:取消watch命令对所有key的监视,用在watch之后,exec或discard之前。总是返回OK
exec
执行一个事务块内队列当中的所有命令 返回事务块内所有命令的返回值,按命令执行的先后顺序排列 当操作被打断时,返回空值nil
discard
取消事务,放弃执行事务块内的所有命令。 事务队列会被清空, 并且客户端会从事务状态中退出 如果正在使用watch命令监视某些key,那么取消所有对key的监视 总是返回OK
事务中的错误
使用事务时可能会遇上以下两种错误:
1、在执行exec之前,入队的命令出错。如语法错误(参数数量错误,参数名错误等等),或者其他更严重的错误,比如内存不足。
此类错误客户端以前的做法是检查命令入队时的返回值,如果是QUEUED,那么入队成功;否则,就是入队失败 从Redis 2.6.5开始,服务器会对命令入队失败的情况进行记录,并在客户端调用exec时,拒绝执行并自动放弃这个事务 在Redis 2.6.5以前,服务器只执行事务中那些入队成功的命令,而忽略那些入队失败的命令
2、在exec调用之后,如事务中的命令可能处理了错误类型的键。此类错误并没有进行特别处理,即使事务中有某个/某些命令在执行时产生了错误,事务中的其他命令仍然会继续执行
为什么Redis不支持回滚(roll back)
Redis命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
鉴于没有任何机制能避免程序员自己造成的错误,并且这类错误通常不会在生产环境中出现,Redis选择了更简单、更快速的无回滚方式来处理事务。所以Redis 的内部可以保持简单且快速。