Redis事务

Redis事务_第1张图片

"你经过我,每个灿烂时刻。我才真正学会如你般自由~" 


Redis事务? vs Mysql

        了解过Mysql的友友们一定不会陌生,它其实就由一组DML(数据操纵语言,例如:INSERT 、UPDATE)语句组成的。谈到事务就得谈到它的特性——ACID。

● 原子性(Atomicity):把多个操作打包成一个整体。

● 持久性(Durability):事务做出修改时,都会存储到硬盘上。

● 隔离性(Isolation):"事务并发"执行时,会涉及到的一系列问题。

● 一致性(Consistency):事务执行前,和事务执行后,数据不能超出预期。

        Redis中的事务,同Mysql的事务相比,就是幼稚园较之于高等学府。

Redis事务与原子性?

Redis事务_第2张图片

        我们任意去搜索查找资料,看看Redis事务具不具备原子性,可是,我们得到的结果是具有争议的!但,原子性的定义是:

        "一个事务的所有操作要么不间断地全部被执行,要么一个也没有执行。"

        我们再来打开看看官方文档对Redis事务(Transaction)释义:
Redis事务_第3张图片       现如今很多人认为的原子性是Mysql这里的原子性,它也是将所有的操作打包在一起,要么全部 "执行成功" ,要么全部不执行。如果事务中的某些操作执行失败,可以使用回滚rollback,把中间的操作全部退回。

        但从最本意来说,Redis是做到了上述原子性的含义的。它可以把多个操作打包在一起,要么全部都执行,要么全部都不执行。

        可是,Redis不支持回滚操作,当事务中的若干操作执行失败,那就失败吧。所以,谈论原子性时,是更加贴合Mysql中的原子性的,打包一起+回滚操作(正确执行)。

Redis事务与持久性\隔离性\一致性?

● 不具备持久性: 因为Redis本身就是内存数据库,数据存储的主要媒介是在内存中的。虽然我们在前面知道Redis的RDB、AOF,但这里和持久化机制和事务没什么直接关系。

● 不涉及隔离性: 隔离性通常都是在事务并发的场景出现,而Redis是一个单线程模型程序,所有的请求\事务,都是串行执行的。

● 不具备一致性: redis没有Mysql那样的严格约束,没有回滚机制,事务中一旦某些若干操作执行失败,就会产生一些不一致的情况。


Redis事务原理

        Redis的官方文档,对Redis的事务做了准确的描述:

Redis事务_第4张图片

        Redis事务的主要意义,就在于 “打包”,避免其他客户端的命令,干扰插队到事务间的操作中。

        Redis实现事务,引入了一个队列(这个队列每个客户端都有一个)。开启事务时,客户端此时输入的命令,就会将这些命令发送给服务器,并且进入这些队列之中(不是立即执行)。一旦,遇到了"执行事务",就会把队列里的这些任务按照顺序依次执行。

Redis事务_第5张图片

        显然,Redis没有在事务的设计搞得像Mysql一样那么复杂,而是从简至上。Mysql的事务,需要在背后付出更大的代价。比如空间上,例如MVCC机制等大量的数据结构、日志等等,时间上,更大的执行开销。

        如果Redis同Mysql一样了,谁还会重新使用Redis?

Redis事务的应用场景:        

Redis事务_第6张图片

        现如今我们要抢“华晨宇2023火星演唱会——南京站”的门票。可以想象同几十万人抢票是一个怎样的并发场景。

         比如官方开放的票数为30000张,如果实际下单抢到票的人数为30001,那一定是出错了的。

Redis事务_第7张图片

        如果将有并发场景意识的人,看到这份代码就能够道出其中不安全的地方。这是很简单的存在“线程安全”问题的代码。如果是在多线程模型下,我们会使用加锁的方式,来保障门票的原子性。        

        但,在Redis中可以直接使用事务解决,因为Redis是单线程模型,Redis中的事务都是按序执行,不存在“插队”的情况。         Redis事务_第8张图片

        这个场景中即便没有加锁,也不会出现超卖的问题。


Redis事务操作

        Redis事务主要的3个操作命令分别为:

○ MULTI: 开启事务

○ EXEC:  执行事务

○ DISCARD: 放弃当前事务

Redis事务_第9张图片

        在服务器事务的队列中,保存了这里的请求,但不会立即执行!我们此时打开另外一个客户端查看对应的key数据时,是查不到的!        Redis事务_第10张图片

        我们一旦执行了EXEC命令,事务操作就会被真正执行,此时我们再从另外一个客户端查看对应key数据就能够查到了。

Redis事务_第11张图片         如果想放弃当前事务.此时直接清空事务队列.之前的操作都不会真正执⾏到。
Redis事务_第12张图片

        如果一个客户端在开启事务后,并且发送了若干条命令,此时突然服务器重启,这个事务会怎么办? ——此时的效果,也就相当于DISCARD,什么也不会执行。

 

WATCH监控

        在执⾏事务的时候,如果某个事务中修改的值,被别的客⼾端修改了。从而导致数据不一致的情况。Redis事务_第13张图片

        WATCH监控某个Key是否在事务执行前,发生了改变。如果此时WATCH检测到这个Key被修改了,那么事务再执行EXEC,事务里的操作命令就不会执行了。Redis事务_第14张图片

                

WATCH原理

        即便Redis不支持隔离性,但至少也得告诉用户,当前的操作是有风险的。

        WATCH实现的原理,类似于一个“乐观锁”。那什么是“乐观锁”呢?什么是“悲观锁”呢?这些都不是指具体的锁,而是指的锁的特征。

• 乐观锁: 加锁之前,就有心理预期,预期接下来锁冲突的概率低。例: 本号机制和CAS算法

• 悲观锁: 加锁之前,就有心理预期,预期接下来锁冲突的概率高。例: C++、Linux涉及到的mutex

        不同的锁类型,解决的成本是不一样的。乐观锁相较于悲观锁,开销要小成本更低。

• 当开启事务的时候,如果对watch的key进⾏修改,就会记录当前key的"版本号"。

• 在真正提交事务的时候,如果发现当前服务器上的key的版本号已经超过了事务开始时的版本号,就会让事务执⾏失败。

Redis事务_第15张图片


总结:

        Redis中的事务要比Mysql 的事务简单太多了。

• 弱化的原⼦性:redis没有"回滚机制".只能做到这些操作"批量执⾏".不能做到"⼀个失败就恢复到初始状态"。

• ⼀致性:不涉及"约束".也没有回滚.MySQL的⼀致性体现的是运⾏事务前和运⾏后,结果都是合理有效的,不会出现中间⾮法状态。

• 隔离性:也没有隔离级别,因为不会并发执⾏事务(redis单线程处理请求)。

• 持久性:Redis是内存数据库。持久化机制是redis-server⾃⼰的事情和事务⽆关.

Redis事务_第16张图片


本篇到此结束,感谢你的阅读。

祝你好运,向阳而生~ 

Redis事务_第17张图片

你可能感兴趣的:(redis,redis,数据库)