码迷,mamicode.com
首页 > 其他好文 > 详细

Redis高级进阶

时间:2015-12-05 14:16:15      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:

一、redis中的事务

在关系型数据库中事务是必不可少的一个核心功能,生活中也是处处可见,比如我们去银行转账,首先需要将A账户的钱划走,然后存到B账户上,这两个步骤必须在同一事务中,要么都执行,要么都不执行,不然钱凭空消失了,换了谁也无法接受。

同样,redis中也为我们提供了事务,原理是:先把一组同一事务中的命令发送给redis,然后redis进行依次执行。

1、事务的语法:

 

multi
命令1
命令2
...
exec

 

解释下语法:首先通过multi命令告诉redis:“下面我发给你的命令是属于同一事务的,你呢,先不要执行,可以把它们先存储起来”。redis回答:“okay啦”。而后我们就发送银行转账的命令1和命令2,这时redis将遵从约定不会执行命令,而是返回queued,表示把这两条命令存储到等待执行的事务队列中了。最后我们发送exec命令,redis开始依次执行在等待队列中的命令,完成一个事务的操作。

redis保证事务中所有命令要么全执行,要么都不执行。如果在发送exec前客户端断线了,redis会清空等待的事务队列,所有命令都不会执行。而一旦发送了exec,即使在执行过程中客户端断线了也没有关系,因为redis早已存储了命令。

下面我们模拟下银行转账的业务,从银行A转账5000到银行B,中间企图修改银行A的余额,这时看看能否转账成功并保证金额正确?

  • 先给银行A 和B分别初始化10000元。
127.0.0.1:6379> set bankA 10000
OK
127.0.0.1:6379> get bankA
"10000"
127.0.0.1:6379> set bankB 10000
OK
127.0.0.1:6379> get bankB
"10000"
  • 进行转账业务操作:
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby bankA 5000
QUEUED
127.0.0.1:6379> incrby bankB 5000
QUEUED
127.0.0.1:6379> 
  • 重新打开一个session,模拟修改银行A的余额,比如取10000元,这时钱被取了,余额为0
127.0.0.1:6379> decrby bankA 10000
(integer) 0
127.0.0.1:6379> get bankA
"0"
  • 到第一个session中执行事务
127.0.0.1:6379> exec
1) (integer) -5000   #这里假设余额可以透支,哈哈。变成﹣5000,而不是原来想的5000,如果实际业务,这时是无法进行转账的。事务保证了余额正确
2) (integer) 15000

2、事务错误处理

如果在执行一个事务时,里面某个命令出错了,redis怎么处理呢?在redis中,需要分析导致命令错误的原因,不同的原因会有不同的处理方式。

1)语法错误

语法错误是指该命令不存在或者参数个数不正确。对于这类错误,redis(2.6.5之后的版本)的处理方式是直接返回错误,全部不执行,即使里面有正确的命令。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set key value
QUEUED
127.0.0.1:6379> set key
(error) ERR wrong number of arguments for set command
127.0.0.1:6379> iiiget key
(error) ERR unknown command iiiget
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get key
(nil)     #事务中有语法错误的命令,即使有一个命令正确也不会被执行
127.0.0.1:6379> 

2)运行错误

运行错误是指命令在执行的时候报错,比如用散列的命令操作集合类型的键。这类错误在运行前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"

可见sadd key 2出错了,但是set key 3依然被执行了。

redis中的事务不像关系型数据库有回滚机制,为此如出现这样的问题,开发者必须自己收拾造成这样的烂摊子了。

为了保证尽量不出现命令和数据类型不匹配的运行错误,事前规划数据库(如保证键名规范)是尤为重要的。

3、watch命令

watch命令可以监控一个和多个键,一旦被监控键的值被修改,阻止之后的一个事务执行(即执行exec时返回nil,但这时watch监控也会失效),还记得上面转账吗?当在转账事务过程中,bankA被取走了10000,余额变成0,这时操作转账时应该提示余额不足,无法转账。可以使用watch命令来阻止转账事务的执行。下面优化一下上面的转账业务:

127.0.0.1:6379> watch bankA  #监控银行A账号
OK
127.0.0.1:6379> decrby bankA 10000
(integer) 0
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby bankA 5000
QUEUED
127.0.0.1:6379> incrby bankB 5000
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get bankA
"0"
127.0.0.1:6379> get bankB
"10000"
127.0.0.1:6379>

二、生存时间

 

Redis高级进阶

标签:

原文地址:http://www.cnblogs.com/mysql-dba/p/5021450.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!