redis学习 第四章进阶----事务

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haitianxiaowu1/article/details/52872744

跟着Redis入门指南学习

第四章 进阶----事务

redis中事务就是一组命令集合,事务通命令一样都是redis的最小执行单位。事务的原理是先将一个事务的命令发送给扔地上,然后再让扔地上一次执行这些命令。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> sadd user:1:following 2
QUEUED
127.0.0.1:6379> sadd user:2:followers 1
QUEUED
127.0.0.1:6379> exec
1) (integer) 1
2) (integer) 1
首先使用multi命令告诉redis:下面我发给你的命令属于同一个事务,你先不要执行,而是把它暂存起来。redis回答:OK,下面两条命令先进入等待执行的事务队列中了。所有命令放入后,exec告诉redis执行事务。返回值为对应命令顺序的返回值。

4.1.2 错误处理

如果一个事务中的某个命令执行出错,redis会怎么处理?

(1)语法错误     

         语法错误指命令不存在或者命令参数的个数不对

127.0.0.1:6379> multi
OK
127.0.0.1:6379> get key value
(error) ERR wrong number of arguments for 'get' command
127.0.0.1:6379> set key value
QUEUED
127.0.0.1:6379> errorcommand key
(error) ERR unknown command 'errorcommand'
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
只要有一个命令有语法错误,执行exec命令后redis都会直接返回错误,连语法正确的命令也不会执行。

(2)运行错误

运行错误指在命令执行时出现的错误,比如使用散列类型的命令操作集合类型的健,这种错误在实际执行之前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
第二句出现错误,第三句继续执行。redis的事务没有关系数据库事务提供的回滚功能(rollback)。故,必须在开发者必须在事务执行出错后自己收拾剩下的摊子。

4.1.4  watch 命令介绍

在一个事务中只有当所有命令都一次执行完后才能得到每个结果的返回值,可是有些情况下需要先获得一条命令的返回值,然后在根据这个值执行下一条命令。如incr命令曾说过使用get和set命令实现incr函数会出现竞态条件。如果用事务来实现incr函数来防止竞态条件,可是因为事务中的每个命令的执行结果都是最后一起返回的,所以无法将前一条命令的结果作为下一条命令的参数,即在执行set命令时无法获得get命令的返回值,也就无法做到增1的功能。

为了解决这个问题,新思路:在get获取到健值后保证该健值不被其他客户端修改,知道函数执行完成后才允许其他客户端修改该健值,这样也可以防止竞态条件。要实现这一思路需要请出事务家族的另一个成员:watch。watch命令可以监控一个或多个健,一旦其中有一个健被修改(或删除),之后的事务就不会执行。监控一直持续到exec命令(事务中的命令是在exec之后才执行的,所以在multi命令后可以修改watch监控的健值),如:

127.0.0.1:6379> set key 1
OK
127.0.0.1:6379> watch key
OK
127.0.0.1:6379> set key 2
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set key 3
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get key
"2"
上例中在执行watch命令后、事务执行之前修改了key的值(set key 2),所以最后事务中的命令set key 3 没有执行,exec命令返回空值结果。学会了watch命令就可以通过事务自己实现incr函数,伪代码如下:

def incr($key)
      watch $key
      $value = get $key
         if not $value
                  $value = 0
          $value = $value +1
      multi
      set $key,$value
          result = exec
        return result[0]
因为exec命令返回值是多行字符串类型,所以代码中使用result[0]来获取其中第一结果。

4.2 生存时间

4.2.1 命令介绍

在实际的开发中常常会遇到一些有时效的数据,比如限时优惠活动、缓存或验证码等,过了一定的时间就需要删除这些数据。在关系数据库中一般需要额外的一个字段记录到期时间,然后定期检测删除过期数据。而在redis中可以使用exprire命令设置一个生存时间,到时间后redis会自动删除它。

expire命令的使用方法为expire key seconds ,其中seconds参数表示健的生存时间,单位是秒,如果想让session:1 健在15分钟后被删除:

127.0.0.1:6379> set session:1 uid1314
OK
127.0.0.1:6379> expire session:1 900
(integer) 1
expire命令返回1表示设置成功,返回0则表示健不存在或设置失败,例如:
127.0.0.1:6379> expire session:2 900
(integer) 0
如果想知道一个健还有多久的时间被删除,可以使用ttl命令,返回值是健的剩余时间(单位是秒)

127.0.0.1:6379> ttl session:1
(integer) 367
127.0.0.1:6379> ttl session:1
(integer) 356
127.0.0.1:6379> ttl session:1
(integer) 326
127.0.0.1:6379> ttl session:1
(integer) 148
127.0.0.1:6379> ttl session:1
(integer) -2
127.0.0.1:6379> ttl session:1
(integer) -2

随着时间的不同,seession:1健的生存时间逐渐减少,20秒后session:1健会被删除,当健不存在时ttl命令会返回-2.另外同样会返回-1的情况时没有为健设置生存时间(即永久存在,这是建立一个健后的默认情况):

127.0.0.1:6379> set persistKey value
OK
127.0.0.1:6379> ttl persistKey
(integer) -1
如果想取消健的生存时间

127.0.0.1:6379> set foo bar
OK
127.0.0.1:6379> expire foo 20
(integer) 1
127.0.0.1:6379> ttl foo
(integer) 18
127.0.0.1:6379> expire foo 40
(integer) 1
127.0.0.1:6379> ttl foo
(integer) 35
其他只对健值进行操作的命令(如incr、lpush、hset、zrem)均不会影响健的生存时间。

expire命令的seconds 参数必须是整数,所以最小单位是1秒,如果想要更精确的控制健的生存时间应该使用pexpire命令,pexpire命令与expire的唯一区别是前者的时间单位是毫秒,即pexpire key 1000  与expire key 1 等价。pttl命令以毫秒为单位返回健的剩余时间。

展开阅读全文

没有更多推荐了,返回首页