一、Redis 事务是什么
Redis 事务是一个原子性的操作:事务中的所有命令都会序列化,按顺序执行,事务执行过程中不会被其他客户端的命令请求打断.
例如下图:
Redis 事务主要就是用来串联多个命令,防止其他命令插队~
二、Redis 事务命令操作
主要以下三个命令:
Multi:输入此命令开始,之后输入的命令会一次进入命令队列中,但不会执行.
Exec:让 Redis 将之前命令队列中的命令依次执行.
discard:放弃组队(删除队列中的所有命令).
例如 组队 + 执行 ,如下:
例如 组队 + 放弃组队,如下:
Ps:作用类似 MySQL 中的创建事务,提交/回滚事务,但不完全一样:
- MySQL 中开启事务后,会执行之后输入的所有命令,一旦出现错误,会将回滚到开启事务的时候.
- Redis 的使用 multi 命令后,输入的所有命令都不会执行,而是放入一个队列当中,只有执行exec 时才依次执行所有的指令,一旦出现错误,也会出现两种不同的类型(后面会具体讲).
三、Redis 事务中的命令错误处理
3.1、事务中出现命令语法错误
当在事务中出现命令的语法错误,那么在 exec 执行所有组队命令的时候,则会放弃刚刚组队的所有命令任务。
3.2、事务中出现命令逻辑错误
当在事务中出现命令的逻辑错误,那么在 exec 执行所有组队命令的时候,则会放弃刚刚逻辑错误的那一条命令,其他正确的命令正常执行。
四、事务冲突的解决办法
4.1、事务冲突问题
想象这样一个场景:在我的账户里有 1000 块钱,此时我的 朋友1 和 朋友2 要同时从我的账户中取 600 块钱,由于 朋友1 取钱的时候看到的是 1000 元,朋友2 取钱的时候看到的也是 1000 元,因此账户中同时扣款中最后就只剩 -200 元,但实际上我们不允许账户出现负数情况,此时就出现了事务冲突.
如何解决呢?接着往下看~
4.1、方法一:悲观锁
顾名思义,总是假设容易发生所冲突,因此在每次操作前都会进行一个加锁的操作.
例如刚刚 事务冲突问题 中所描述的栗子,悲观锁要做的就是在每个用户操作之前先进行加锁,其他用户要访问这个资源只能先阻塞等待.
适用场景:写操作多(需要加锁的场景多), 读操作少的场景。
4.2、方法二:乐观锁
顾名思义,总假设不容易发生所冲突,因此每次操作前都不会上锁,而是给当前资源加上版本号,操作完后,修改版本号,若有其他用户来进行写操作,会先对比版本号,若版本号不符合预期,则停止操作.
例如当有两个用户同时进行取款操作,先取到款的用户会修改版本号,当用户二取款时就会发现版本号不一样,就不能在执行之前的操作(发现不一致,直接停止操作).
适用场景:适用于读操作多,写操作少的场景,可以提高吞吐量~