跟我一起学Redis之Redis事务简单了解一下

关系数据库中的事务,小伙伴们应该是不陌生了,不管是在开发还是在面试过程中,总有两个问题逃不掉:

说说事务的特性;

事务隔离级别是怎么一回事?

事务处理不好,数据就可能不准确,最终就会导致业务出问题;借此机会简单回顾一下事务特性及其隔离级别,就当是复习了;

事务特性(ACID)

原子性(Atomicity)

指事务内所有操作要么一起执行成功,要么都一起失败(或者说是回滚);如事务经典转账案例:A给B转账,A把钱扣了,但B没有收到;可见这种错误是不能接受的,最终会回滚,这也是原子性的重要性。

一致性(Consistency)

指事务执行前后的状态一致,如事务经典转账案例:A给B互相转账,不管怎么转,最终两者钱的总和还是不变;

持久性(Durability)

指事务一旦提交,数据就已经永久保存了,不能再回滚;

隔离性(Isolation)

指多个并发事务之间的操作互不干扰,但是事务的并发可能会导致数据脏读、不可重复读、幻读问题,根据业务情况,采用事务隔离级别进行对应数据读问题处理。

事务隔离级别

读未提交(Read uncommitted)

指一个事务读取到其他未提交事务的数据。可能导致数据脏读

转账案例:A正在给B转账,本来转的1000,A多输入了个0,变成10000,但此事务还未提交,但此时B查询到转入的是10000,但A取消事务回滚之后,B又查询不到转入的数据。这种情况就是脏读

读已提交(Read committed)

指一个事务只能读取到其他事务已提交的数据,从而解决了脏读的问题。但可能导致数据不可重复读

转账案例:A要给B转账1000,A先查看了一下余额,有1000,然后开始给B转钱,但此时A家里电费通过开启的自动缴费功能,自动从A账户扣除200缴纳电费,并提交;当A转账准备提交,再次确认余额时,钱少了200。这样就导致同一个事务中多次查询的结果不一致,这种情况就是不可重复读

可重复读(Repeatable read)

指事务只要一开启,就不允许其他事务进行修改操作,从而解决了不可重复读问题。但可能导致数据幻读

转账案例:A经常给B转账,到年底了,需要查账,然后开启了一个事务进行查询统计,刚开始查询只是10条转账记录,正准备统计时,因为紧急情况A需要给B转一笔钱应急,从而新增了一条新记录,并提交;而查账事务正在统计中,最后发现转账额和看到的10条转账记录不匹配。这种情况就是幻读

序列化(Serializable )

指事务之间只能串行话执行,就像队列一样,排队进行,这样就解决了幻读的问题,但是这种级别的并发性能不高,非特殊需求,这种级别一般不用。

正文

转入正题,结合关系型数据库的事务来看看Redis中事务有什么不同;

Redis事务是指将多条命令加入队列,一次批量执行多条命令,每条命令会按顺序执行,事务执行过程中不会受客户端传入的命令请求影响。

Redis事务的相关命令如下:

MULTI:标识一个事务的开启,即开启事务;

EXEC:执行事务中的所有命令,即提交;

DISCARD:放弃事务;和回滚不一样,Redis事务不支持回滚。

WATCH:监视Key改变,用于实现乐观锁。如果监视的Key的值改变,事务最终会执行失败。

UNWATCH:放弃监视。

Redis事务和关系型数据库的事务不太一样,它不保证原子性,也没有隔离级别的概念。来,结合命令演示,实战说明一切:

没有隔离级别

image-20201112153132140

如上图所示,当事务开启时,事务期间的命令并没有执行,而是加入队列,只有执行EXEC命令时,事务中的命令才会按照顺序一一执行,从而事务间就不会导致数据脏读、不可重复读、幻读的问题,因此就没有隔离级别

不保证原子性

image-20201112154524168

如上图所示,在通过EXEC执行事务时,其中命令执行失败不会影响到其他命令的执行,并没有保证同时成功和同时失败的原子操作,尽管这样,Redis事务中也没有提供回滚的支持,官方提供了两个理由:

image-20201112160255544

大概的意思就是:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpydjj.html