Redis事务

  • Redis
  • 数据库
  • NoSql
  • 非关系型数据库
  • 事务
大约 3 分钟

一、概念

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

二、Redis事务三特性

1.单独的隔离操作

  • 事务中的所有命令都会序列化、按顺序地执行
  • 事务在执行的过程中,不会被其他客户端发送来的命令请求所打断

2.没有隔离级别的概念

队列中的命令(指令), 在没有提交前都不会实际被执行

3.不保证原子性

事务执行过程中, 如果有指令执行失败,其它的指令仍然会被执行, 没有回滚

三、相关指令

20230203145557

  1. 从输入 Multi 命令开始,输入的命令都会依次进入命令队列(QUEUED)中,但不会执行(类似 Mysql 的 start transaction 开启事务)
  2. 输入 Exec 后,Redis 会将之前的命令队列中的命令依次执行(类似 Mysql 的 commit 提交事务)
  3. 组队 Multi 的过程中可以通过 discard 来放弃组队(类似 Mysql 的 rollback 回顾事务)
  4. 如果在组队阶段报错, 会导致 exec 失败, 那么事务的所有指令都不会被执行,这个情况是具有原子性的

四、事务冲突及解决方案

例如:在购票时,如果只有10张票,当同时有三个请求购票,第一个请求购票6张,第二个请求购票5张,第三个请求购票1张,如果没有事务控制就会出现超卖现象。

1.悲观锁

Pessimistic Lock--总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。

Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。传统的关系型数据库里边也用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

缺点:性能较低

2.乐观锁

Optimistic Lock--总是乐观地假设最好的情况,每次去拿数据的时候都认为别人不会修改这个数据,所以不会上锁,只会要对数据进行更新时判断一下在此期间(拿到数据到更新的期间)别人有没有去更改这个数据,可以使用版本号机制和CAS算法实现。

乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis 就是利用这种 check-and-set 机制实现事务的

3.watch & unwatch

20230204143030

如上图所示,初始值 k1=110 k2=30

在开启事务之前两个Redis连接都执行了 watch k1指令,相当于对k1的版本号进行了一个监控

第一个连接先执行事务 exec,执行成功

第二个连接由于k1的值已被改变,事务终止,就返回了nil,队列中的k1和k2都没有改变

unwatch :取消 watch 命令对所有 key 的监视

如果在执行 watch 命令后,exec 命令或 discard 命令先被执行了的话,那么就不需要再执行 unwatch

上次编辑于: