zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

Redis事务操作

Redis事务 操作
2023-06-13 09:17:16 时间

Redis事务操作

  事务具有ACID特性,即原子性、一致性、隔离性和持久性。用过事务,可以让一段代码要么全部执行要么全都不执行。   由于Redis是NoSQL类型的键值对数据,因此操作事务的方式和关系型数据库有差别。

1、事务的概念和ACID特性

  在数据库层面,事务是指一组操作,这些操作要么全都被成功执行,要么全都不执行。比如某转账的事务里包含两个操作,操作1是从Mike的账户里扣除100元,操作2是在Peter的账户里加100元。假设第二步给Peter账户加100元的操作失败,那么“从Mike账户扣除100元”这个操作即使已经成功执行,也需要回归,从而保证“要么全做要么全都不做”的特性。具体而言,事务具有ACID特性。

  • A表示原子性(Atomicity),即事务是一个不可分割的实体,事务中的操作要么都做,要么全都不执行。
  • C表示一致性(Consistency),即事务前后数据完整性必须一致,假设数据库里有很多完整性约束,比如ID字段不能为空,且必须是10位,在事务执行前后,这些完整性约束不能被违反。
  • I表示隔离性(Isolation),即一个事务内部操作对其他事务是隔离的,并发执行的各事务间不能互相干扰。
  • D表示持久性(Durability),这是指一个事务一旦提交,它对数据库的改变就是永久性的,哪怕数据库出现故障,事务执行后的操作也该丢失。 在事务的ACID特性方面,Redis和传统的关系型数据库有相似点也有差别。

2、实现Redis事务的相关命令

  在Redis里,有4个命令与事务有关:可以用multi命令开启Redis事务,用exec命令提交事务,用discard命令取消事务,用watch命令来监视指定的键值对,从而让事务有条件的执行。

  上面先开启事务,再通过set命令设置值,可以发现,此时的返回结果不是OK,而是QUEUED,表示该命令当前没有执行,而是放到了事务队列中。   通过exec命令执行事务后,会一次性地返回包含在该事务队列中地诸多命令,一旦执行完exec命令,就退出了状态,所以get命令是立即返回结果。

3、通过discard命令撤销事务中的操作

  通过discard命令可以撤销事务里的所有操作。

  通过discard命令撤销事务中的所有操作,那么事务中的所有命令都不会生效,所以我们查看键age在事务操作前后的值并没有发生变化,都是25

4、用watch命令监视指定键

  如果两个或多个事务同时对某个键对应的值进行操作,就需要考虑因并发而导致的影响。   比如某个账户里有1000元,有两个事务同时对该账户进行读取值并加100元的操作。事务A和B读账户时,读到的值均是1000,但是事务B在加100元前,事务A已经把账户值修改为1100,此时事务B就不应该继续把账户值加为1200,而应当终止。   在进行Redis事务相关操作时,可以通过watch命令来监控一个或多个键,如果被监控的键只被事务本身修改,在其他场合没有修改,那么该事务能正确执行,反之被监控的键不仅被本事务修改,在本事务执行时还被其他客户端修改,本事务就不能正确执行。

watch命令一般在开启事务前执行,先通过watch命令监视balance和salary两个键,用multi开启事务后,设置两个键的值,最后提交事务,查看键的值。

下面演示因监控的值被其他客户端修改而导致本事务运行失败的场景。

在一个客户端里运行如下命令:

  上面第一行通过watch命令监控了bonus变量,随后用multi开启事务,再设置bonus的值为1000.此时先不执行exec命令,而是打开另一个命令窗口,执行如下命令:

  上面再新窗口中通过docker exec命令再次进入容器,通过redis-cli连接到服务器后,设置bonus的值为2000(即模仿在事务未提交前数据就已经被外部操作修改)   再次回到已经启动事务的第一个窗口,在其中执行exec命令提交事务,如下所示:

  由于此时监控的bonus已经被其他客户端修改,所以exec命令返回的是nil,表示事务里set bonus 1000没有被执行,而且最后get bonus返回的结果是2000,这说明其他客户端修改watch监控的变量会阻止本事务对该指定键的监控,这是符合预期的。   和watch命令相对应的是unwatch命令,即能取消对所有指定键的监控。注意,unwatch命令只能撤销对所有键的监控,而不能撤销对指定键的监控。