记录每次学习的过程,总结学习的内容,希望能给到自己和别人帮助。

Redis事务和锁机制

Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
Redis事务的主要作用就是串联多个命令防止别的命令插队

multi  exec  discard

从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,
直到输入Exec后,Redis会将之前的命令队列中的命令依次执行。
组队的过程中可以通过discard来放弃组队。

演示 multi 和 exec

执行multi,返回ok并且显示127.0.0.1:6379(TX)
证明已经开启事务 执行set key1 value1
会返回QUEUED 意思是已经将命令组队,但是还没有执行
组队多个命令之后,执行exec命令,会执行组队中的命令
执行成功之后有多少个命令就有多少个ok返回 事务结束

redis6 事件源码分析 redis事务实现原理_redis


演示 multi 和 discard

执行multi开启事务
执行set k1 v1 和set k2 v2
如果不想执行了,就执行discard
返回ok就说明组队的命令都放弃

redis6 事件源码分析 redis事务实现原理_redis6 事件源码分析_02

事务错误的两种情况:

1、组队中某个命令出现了报告错误,执行时整个的所有队列、命令都会被取消。就是在组队阶段的命令出现错误,最终执行的时候,全部在组队的命令都不会成功。

redis6 事件源码分析 redis事务实现原理_redis6 事件源码分析_03


2、如果执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚。

就是组队成功了,但是提交的时候 有成功有失败的情况,哪个失败就不执行哪个,正常的还是会执行

redis6 事件源码分析 redis事务实现原理_redis_04

事务冲突的问题

通过 悲观锁乐观锁 来解决

悲观锁(Pessimistic Lock)

顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
通过在每次操作的时候上锁。在自己操作的时候上锁,等到自己操作完了,释放锁之后,下一个人才能操作。
缺点:效率低

乐观锁(Optimistic Lock)

顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。
通过版本号,所有人都能得到v1.0版本的数据,假设第一个人操作得快,将数据修改了,数据在被修改之后,同步将版本号也修改将数据库中的版本号变成v1.1。第二个人在操作数据的时候,会检查当前数据的版本号check-and-set,跟数据库中的版本号是否一致,v1.0不等于v1.1,所以不能操作。
优点:乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的。

乐观锁的实现,通过watch key [key…]

在执行multi之前,先执行watch key1 [key2],可以监视一个(或多个) key ,如果在事务执行之前这个(或这些) key
被其他命令所改动,那么事务将被打断。

使用两个终端模拟场景:

#在一号终端中首先set一个key-value:
set key 100
#两个终端都监视这个key,返回ok就是证明已经开启了监视
watch key
#两个终端都执行multi开启事务,并且各自组队命令,等待执行exec
#如一号终端执行 incrby key 10    二号终端执行 incrby key 20
multi
incrby key 10
incrby key 20
#在一号终端中先执行exec,再在二号终端执行exec
exec
#一号终端会返回integer(110)成功执行加10的命令
#二号终端会返回nil,类似java中的空,证明二号终端中的命令没有执行下去

一号终端

redis6 事件源码分析 redis事务实现原理_缓存_05


二号终端

redis6 事件源码分析 redis事务实现原理_缓存_06


unwatch

取消 WATCH 命令对所有 key 的监视。
如果在执行 WATCH 命令之后,EXEC 命令或DISCARD
命令先被执行了的话,那么就不需要再执行UNWATCH 了。

watch key
unwatch

redis6 事件源码分析 redis事务实现原理_redis_07

Redis事务三特性

1、单独的隔离操作
事务中的所有命令都会序列化按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
2、没有隔离级别的概念
队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行。
3、不保证原子性
事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚
(组队中有一个失败全部失败,组队成功之后,有哪个失败就失败哪个,其他的正确的还是会执行,与mysql事务中的一个失败全部回滚不一样)

凡心所向,素履以往,生如逆旅,一苇以航。