小贝_redis 高级应用-事务

来源:互联网 发布:淘宝客 编辑:程序博客网 时间:2024/05/17 20:27

redis高级应用-事务

一、redis的事务

二、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 不会停止执行事务中的命令)

1 0
原创粉丝点击