Redis研究(10)—Redis事务和生存时间
一、事务概述
Redis事务是一组命令的集合。事务同命令一样是Redis的最小执行单位,要么执行,要么不执行。
事务的原理是先将属于一个事务的命令发送给Redis,然后在让Redis依次执行这些命令。
Redis在事务中没有立即执行sadd操作,而是返回QUEUED表示这两条命令已经进入等待执行的事务队列中了。
使用EXEC命令告诉Redis将等待执行的事务队列中的所有命令按照发送顺序依次执行。
EXEC返回值就是这些命令的返回值组成的列表,返回值顺序和命令的顺序相同。
Redis保证一个事务中的所有命令要么都执行,要么都不执行。如果在发送EXEC命令前客户端断线了,则Redis会清空事务队列,事务中的所有命令都不会执行。而一旦客户端发送了EXEC命令,所有的命令就都会执行,即使此后客户端断线也没有关系,因为Redis中已经记录了所有要执行的命令。
Redis的事务还能保证一个事务内的命令依次执行而不被其他命令插入。
二、错误处理
事务中的某个命令执行出错,怎么办?
(1)语法错误,指命令不存在或者命令参数的个数不对。
3个命令,一个正确,两个错误,而只要有一个命令有语法错误,执行EXEC命令后Redis就会直接返回错误,连语法正确的命令也不会执行。
(2)运行错误,指命令执行时出现的错误,比如使用散列类型的命令操作集合类型的键。在执行以前Redis无法发现,所以在事务中这样的命令会被接受并执行,
一条命令出现了运行错误,事务里其他的命令依然会继续执行。
虽然sadd key 2出现了错误,但是set key 3依然执行了。
Redis事务没有回滚功能。
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单位是毫秒。