redis高级应用-事务
一、redis的事务
二、redis实现事务
三、redis事务问题
事务提供了一种“将多个命令打包,然后一次性、按顺序地执行”的机制, 并且事务在执行的期间不会主动中断 —— 服务器在执行完事务中的所有命令之后, 才会继续处理其他客户端的其他命令。
redis 通过 multi 、disacrd、exec 和 watch四个命令来实现事务功能
1、redis事务简单例子
127.0.0.1:6379> multi
OK
127.0.0.1:6379>set name xiaobei
QUEUED
127.0.0.1:6379>get name
QUEUED
127.0.0.1:6379>exec
1)OK
2)"xiaobei"
2、详解redis事务过程
2.1、一个事务从开始到执行会经历以下三个阶段:a、开始事务。b、命令入队。c、执行事务。
2.1.1、开始事务
127.0.0.1:6379>multi
(备注: 这个命令的作用就是让客户端从非事务状态切换到事务状态)
2.1.2、命令入队
127.0.0.1:6379> set name xiaobei
QUEUED
(备注: 如果客户端处于非事务状态下,所有发送给服务端的命令都会立即执行。相反,服务器在收到来自客户端的命令时,不会立即执行命令, 而是将这些命令全部放进一个事务队列里, 然后返回 QUEUED , 表示命令已入队)
命令入队的流程图:
2.1.3、执行事务
127.0.0.1:6379>exec
1)OK
2)"xiaobei"
(备注: 当 exec 命令执行时, 服务器根据客户端所保存的事务队列,以先进先出(FIFO)的方式执行事务队列中的命令: 最先入队的命令最先执行, 而最后入队的命令最后执行。当事务队列里的所有命令被执行完之后, exec命令会将回复队列作为自己的执行结果返回给客户端, 客户端从事务状态返回到非事务状态, 至此, 事务执行完毕)
执行事务的流程图:
3、撤销事务
127.0.0.1:6379> multi
OK
127.0.0.1:6379>set name xiaobei
QUEUED
127.0.0.1:6379>discard
OK
127.0.0.1:6379>exec
(error) ERREXEC without MULTI
(备注: discard 命令用于取消一个事务, 它清空客户端的整个事务队列, 然后将客户端从事务状态调整回非事务状态,最后返回字符串 OK 给客户端, 说明事务已被取消)
4、带watch的事务
watch 命令用于在事务开始之前监视任意数量的键: 当调用 exec命令执行事务时, 如果任意一个被监视的键已经被其他客户端修改了,那么整个事务不再执行, 直接返回失败
4.1、例子
4.2、以下表格展示了客户端A是如何失效
时间 |
客户端A |
客户端B |
t1 |
watch name |
|
t2 |
multi |
|
t3 |
set name xiaobei |
|
t4 |
|
set name hello |
t5 |
exec |
|
(备注: 在时间 t4 ,客户端 B 修改了 name 键的值, 当客户端 A 在 t5 执行 exec 时,Redis 会发现 name 这个被监视的键已经被修改,因此客户端 A 的事务不会被执行,而是直接返回失败)
三、redis事务问题
1、为什么redis不支持回滚
a、redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中
b、因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速
2、事务状态下的 discard、multi和watch命令
除了 exec之外, 服务器在客户端处于事务状态时,不加入到事务队列而直接执行的另外三个命令是 discard、multi和watch。
discard命令用于取消一个事务, 它清空客户端的整个事务队列,然后将客户端从事务状态调整回非事务状态, 最后返回字符串 OK 给客户端, 说明事务已被取消。
redis的事务是不可嵌套的, 当客户端已经处于事务状态,而客户端又再向服务器发送 multi时, 服务器只是简单地向客户端发送一个错误, 然后继续等待其他命令的入队。 multi命令的发送不会造成整个事务失败, 也不会修改事务队列中已有的数据。
watch只能在客户端进入事务状态之前执行, 在事务状态下发送watch命令会引发一个错误, 但它不会造成整个事务失败, 也不会修改事务队列中已有的数据(和前面处理 multi的情况一样)
3、在事务和非事务状态下执行命令
a、非事务状态下的命令以单个命令为单位执行,前一个命令和后一个命令的客户端不一定是同一个;而事务状态则是以一个事务为单位,执行事务队列中的所有命令:除非当前事务执行完毕,否则服务器不会中断事务,也不会执行其他客户端的其他命令。
b、在非事务状态下,执行命令所得的结果会立即被返回给客户端;而事务则是将所有命令的结果集合到回复队列,再作为 EXEC 命令的结果返回给客户端
4、事务中的错误
1、使用事务时可能会遇上以下两种错误:
a、事务在执行EXEC 之前,入队的命令可能会出错。比如说,命令可能会产生语法错误(参数数量错误,参数名错误,等等),或者其他更严重的错误,比如内存不足(如果服务器使用 maxmemory 设置了最大内存限制的话)。
b、命令可能在EXEC 调用之后失败。举个例子,事务中的命令可能处理了错误类型的键,比如将列表命令用在了字符串键上面等。
2、实例
(备注: 最重要的是记住这样一条, 即使事务中有某条/某些命令执行失败了, 事务队列中的其他命令仍然会继续执行—— redis 不会停止执行事务中的命令)
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u014795720/article/details/47373331