Redis研究(十)—Redis事务和生存时间

来源:互联网 发布:js给input赋值 编辑:程序博客网 时间:2024/05/19 04:56

一、事务概述

Redis事务是一组命令的集合。事务同命令一样是Redis的最小执行单位,要么执行,要么不执行。

事务的原理是先将属于一个事务的命令发送给Redis,然后在让Redis依次执行这些命令。

Redis在事务中没有立即执行sadd操作,而是返回QUEUED表示这两条命令已经进入等待执行的事务队列中了。

使用EXEC命令告诉Redis将等待执行的事务队列中的所有命令按照发送顺序依次执行。

EXEC返回值就是这些命令的返回值组成的列表,返回值顺序和命令的顺序相同。


Redis保证一个事务中的所有命令要么都执行,要么都不执行。如果在发送EXEC命令前客户端断线了,则Redis会清空事务队列,事务中的所有命令都不会执行。而一旦客户端发送了EXEC命令,所有的命令就都会执行,即使此后客户端断线也没有关系,因为Redis中已经记录了所有要执行的命令。


Redis的事务还能保证一个事务内的命令依次执行而不被其他命令插入。


二、错误处理

事务中的某个命令执行出错,怎么办?

(1)语法错误,指命令不存在或者命令参数的个数不对。命令可能会产生语法错误(参数数量错误,参数名错误,等等),或者其他更严重的错误,比如内存不足

(如果服务器使用 maxmemory 设置了最大内存限制的话)

3个命令,一个正确,两个错误,而只要有一个命令有语法错误,执行EXEC命令后Redis就会直接返回错误,连语法正确的命令也不会执行。

在 Redis 2.6.5 以前,Redis 只执行事务中那些入队成功的命令,而忽略那些入队失败的命令

不过,从 Redis 2.6.5 开始,服务器会对命令入队失败的情况进行记录,并在客户端调用EXEC 命令时,拒绝执行并自动放弃这个事务。

(2)运行错误,指命令执行时出现的错误,比如使用散列类型的命令操作集合类型的键。在执行以前Redis无法发现,所以在事务中这样的命令会被接受并执行,

一条命令出现了运行错误,事务里其他的命令依然会继续执行。

虽然sadd key 2出现了错误,但是set key 3依然执行了。


取消一个事务:


Redis 在事务失败时不进行回滚,而是继续执行余下的命令

1.Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,

失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。

2.因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。

鉴于没有任何机制能避免程序员自己造成的错误,并且这类错误通常不会在生产环境中出现,所以 Redis 选择了更简单、更快速的无回滚方式来处理事务。


三、watch命令

事务中每个命令的执行结果都是最后一期返回的,无法将前一条命令的结果作为下一条命令的参数。

比如说get值,+1,再set

为了解决这个问题,在get获得键值后保证该键值不被其他客户端修改,直到函数执行完成后才允许其他客户端修改该键值。可以防止竞态条件。

执行watch命令后,事务执行前修改了key的值,set key 2,所以最后事务中的命令set key 3没有执行,EXEC命令返回空结果。


由于watch命令的作用只是当被监控的键值被修改后阻止之后一个事务的执行,而不能保证其他客户端不修改这一键值,所以我们需要在EXEC执行失败后重新执行整个函数。

执行EXEC后会取消所有键的监控,也可以用unwatch命令来取消监控。


四、生存时间

使用expire命令设置一个键的生存时间,到时候后redis会自动删除它。

如果想让session:29e3d键在15分钟后被删除

返回1表示成功,0表示键不存在或者设置失败。

一个键还有多久时间被删除,可以用ttl命令,返回值是键的剩余时间(单位s)

当键不存在时ttl返回-1.同样会返回-1是没有为键设置生存时间(永久存在)。


想取消生存时间设置,即恢复永久,用persist命令。成功1,失败0

除次之外,还可以set或getset命令为键赋值也会同时清除键的生存时间。


使用expire会重新设置键的生存时间。

其他只对键值进行操作的命令(incr、lpush、hset、zrem)都不会影响键的生存时间。


expire命令时间参数必须是整数,s。更精确,使用pexpire,单位是毫秒。对应可以用pttl返回剩余时间。


如果watch命令监测了一个拥有生存时间的键,该键时间到期后自动删除并不会被watch命令认为该键被改变。


另外两个命令

expireat和pexpireat,与前面差别使用unix时间作为时间参数。expireat单位是秒,pexpireat单位是毫秒。


引用

http://my.oschina.net/OutOfMemory/blog/300173


0 0