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

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

一、事务概述

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

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

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

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

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

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


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


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


二、错误处理

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

(1)语法错误,指命令不存在或者命令参数的个数不对。

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

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

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

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

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

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


Redis事务没有回滚功能。

Redis不支持回滚功能,也使得Redis在事务上可以保持简洁和快速。两种错误,语法错误和运行错误完全可以在开发时找出并解决。


三、watch命令

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

比如说get值,+1,再set

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

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

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


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

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


四、生存时间

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

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

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

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

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

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

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

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


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

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

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

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


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

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

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


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


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


另外两个命令

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