【Redis】Transaction(事务)

🎯前言

Redis事务是一个组有多个Redis命令的集合,这些命令可以作为一个原子操作来执行。

Redis事务通常用于以下两种情况:

  1. 保证操作的原子性:在多个命令的执行过程中,如果有一个命令执行失败,整个事务都需要回滚(撤销)到事务开始前的状态,确保数据的一致性。

  2. 实现乐观锁:通过在事务中监视某些键,如果这些键在事务执行之前被其他客户端修改,则事务可以取消执行,从而避免了出现死锁或数据不一致的情况。

在Redis中,通过使用MULTI命令开始一个事务,然后将多个命令添加到事务中,最后使用EXEC命令来执行这些命令。如果事务中的任何一个命令执行失败,可以使用DISCARD命令来取消事务,或者使用UNWATCH命令来取消对键的监视。

Redis的与事务相关的命令说明:

  1. DISCARD:用于取消一个事务,放弃事务中所有未执行的命令,并恢复到事务开始前的状态。
  2. EXEC:用于执行一个事务,将所有已组装但未执行的命令一次性执行,并返回执行结果。
  3. MULTI:用于组装一个事务,将多个命令放入事务中,等待后续的EXEC命令来执行这些命令。
  4. UNWATCH:用于取消对所有键的监视,这个命令通常在使用WATCH命令监视一些键时使用,以确保在执行事务之前,这些键没有被其他客户端修改。
  5. WATCH:用于监视一些键,一旦这些键在事务执行之前被改变,则取消事务的执行。这个命令通常与MULTI命令一起使用,用于实现类似于"乐观锁"的效果。

这些命令通常用于保证在Redis事务中的操作的原子性和一致性。通过将多个命令放入同一个事务中,可以确保这些命令作为一个整体一起执行,并且在有其他客户端对被监视的键进行修改时,能够适当地处理冲突和错误。

Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:

  1. 批量操作在发送 EXEC 命令前被放入队列缓存。
  2. 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
  3. 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

一个事务从开始到执行会经历以下三个阶段:

  1. 开始事务。
  2. 命令入队。
  3. 执行事务。

🎯DISCARD(取消事务,放弃执行事务块内的所有命令)

说明:

  • DISCARD命令是Redis事务的一部分,用于取消当前事务,恢复到事务开始前的状态。
  • 使用DISCARD命令可以在事务执行过程中取消事务,并且不会对已有的键值产生影响。

时间复杂度:

  • O(1)。

返回值:

  • 总是返回 OK 

以下是一个使用DISCARD命令的示例代码:

127.0.0.1:6379> multi # 开始一个事务
OK
127.0.0.1:6379> set key1 "value1" # 添加一个SET命令到事务中
QUEUED
127.0.0.1:6379> set key2 "value2" # 添加另一个SET命令到事务中 
QUEUED
127.0.0.1:6379> discard # 取消事务,不执行SET命令
OK
  • 在这个示例中,通过使用DISCARD命令,第一个SET和第二个SET命令不会生效,并且整个事务都被取消了。
  • 单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
  • 事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

🎯EXEC(执行所有事务块内的命令)

说明:

  • EXEC命令是Redis事务的一部分,用于执行事务中所有添加的命令。
  • 当使用EXEC命令时,事务中的所有命令将作为一个原子操作被执行,如果有一个命令执行失败,整个事务将回滚到开始前的状态。
  • 举例:假如某个(某些) key 正处于 WATCH 命令的监视之下,且事务块中有和这个(或这些) key 相关的命令,那么 EXEC 命令只在这个(或这些) key 没有被其他命令所改动的情况下执行并生效,否则该事务被打断终止。

时间复杂度:

  • 事务块内所有命令的时间复杂度的总和。

返回值:

  • 事务块内所有命令的返回值,按命令执行的先后顺序排列。
  • 当操作被打断时,返回空值 nil 。

以下是一个使用EXEC命令的示例代码:

# 事务被成功执行


127.0.0.1:6379> MULTI
OK


127.0.0.1:6379> INCR userid
QUEUED


127.0.0.1:6379> INCR userid
QUEUED


127.0.0.1:6379> INCR userid
QUEUED

redis> PING
QUEUED

redis> EXEC
1) (integer) 1
2) (integer) 2
3) (integer) 3
4) PONG


# 监视 key ,且事务成功执行

127.0.0.1:6379> WATCH lock lock_value
OK

127.0.0.1:6379> MULTI
OK

127.0.0.1:6379> SET lock "xiaojian"
QUEUED

127.0.0.1:6379> INCR lock_value
QUEUED

127.0.0.1:6379> EXEC
1) OK
2) (integer) 1


# 监视 key ,且事务被打断

127.0.0.1:6379> WATCH lock lock_value     # 监视lock键 和 lock_value键
OK

127.0.0.1:6379> MULTI     # 开始一个事务
OK

127.0.0.1:6379> SET lock "mr"        # 就在这时,另一个客户端修改了 lock 键的值,另一个客户端修改 这个被监视的 lock键,此时事务必定是失败的!
QUEUED

127.0.0.1:6379> SET lock_value    # 此时就算 lock_value 没被修改,事务失败已成定局。
QUEUED

127.0.0.1:6379> EXEC                  # 因为 lock 被其他客户端修改,事务自动取消执行。
(nil)

🎯MULTI(标记一个事务块的开始)

说明:

  • MULTI命令是Redis事务的一部分,用于开始一个新事务,并将后续的命令添加到这个事务中,直到使用EXEC命令执行这些命令为止。
  • 事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由 EXEC 命令原子性(atomic)地执行。
  • 使用MULTI命令可以将多个命令添加到事务中,并且可以在需要时使用DISCARD命令取消事务,或者使用EXEC命令执行事务中的所有命令。

时间复杂度:

  • O(1)。

返回值:

  • 返回 OK 。

以下是一个使用MULTI命令的示例代码:

127.0.0.1:6379> multi # 标记事务开始
OK
127.0.0.1:6379> set key1 value1  # 多条命令按顺序入队
QUEUED
127.0.0.1:6379> set key2 valus2
QUEUED
127.0.0.1:6379> exec # 执行
1) OK
2) OK



  • 在这个示例中,通过使用MULTI命令,将两个SET命令添加到事务中,使用EXEC命令执行事务中的所有命令。或者可以使用DISCARD命令取消事务,这样两个SET命令都不会被执行。
  • MULTI命令是Redis事务的一个重要组成部分,用于开始一个新事务并将后续的命令添加到这个事务中。

🎯UNWATCH(取消 WATCH 命令对所有 key 的监视)

说明:

  • UNWATCH命令是Redis事务的一部分,用于取消对所有键的监视,这个命令通常在使用WATCH命令监视一些键时使用,以确保在执行事务之前,这些键没有被其他客户端修改。
  • 当使用UNWATCH命令时,Redis将取消对所有键的监视,如果有其他客户端在这些键上执行了修改操作,也不会影响当前客户端的事务执行。
  • 如果在执行 WATCH 命令之后, EXEC 命令或 DISCARD 命令先被执行了的话,那么就不需要再执行 UNWATCH 了。
  • 因为 EXEC 命令会执行事务,因此 WATCH 命令的效果已经产生了;而 DISCARD 命令在取消事务的同时也会取消所有对 key 的监视,因此这两个命令执行之后,就没有必要执行 UNWATCH 了。

时间复杂度:

  • O(1)。

返回值:

  • 总是 OK 。

以下是一个使用UNWATCH命令的示例代码:

127.0.0.1:6379> WATCH lock lock_value
OK

127.0.0.1:6379> UNWATCH
OK

🎯WATCH(监视一个或多个key ,在事务执行之前这个或这些 key 被其他命令所改动,那么事务将被打断)

说明:

  • WATCH命令是Redis事务的一部分,用于监视一些键,一旦这些键在事务执行之前被其他客户端修改,则事务会取消执行,从而避免了出现死锁或数据不一致的情况。
  • 当使用WATCH命令时,客户端将开始监视指定的键,如果这些键在其他客户端上被修改,当前客户端的事务将自动取消执行。

时间复杂度:

  • O(1)。

返回值:

  • 总是返回 OK 。

以下是一个使用WATCH命令的示例代码:

127.0.0.1:6379> watch key1  # 监视一个键  (注意:可以一条命令监视多个键  如:WATCH key1 key2)

127.0.0.1:6379> watch key2  # 再监视一个键  

127.0.0.1:6379> multi # 开始一个事务  

127.0.0.1:6379> set("key1", "value1")  # 在被监视的键上进行SET操作  

127.0.0.1:6379> set("key2", "value2")  # 在被另外
  • 当使用WATCH命令监视了两个键后,开始一个新事务,并在被监视的键上执行SET操作,如果这些键在其他客户端上被修改,事务会自动取消执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/38469.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

挖矿记录+解决方案:利用GitLab组件对服务器进行挖矿导致CPU占用200%

文章目录 什么是云服务器挖矿?事件记录事件分析产生影响解决方案后期预防什么是云服务器挖矿? 云服务器挖矿是指利用云服务器从事赚取比特币的活动。比特币是一种虚拟数字货币,挖矿是将一段时间内比特币系统中发生的交易进行确认,并记录在区块链上形成新区块的过程。 用于…

【字节流】写数据的三种方式以及两个问题

字节流写数据 1.字节流写数据三种方式 void write(int b):将指定的字节写入此文件输出流一次写一个字节数据 package com.bytestream; import java.io.FileOutputStream; import java.io.IOException; public class FileOutputStreamDemo02 {public static void ma…

融云「北极星」数据监控平台:数据可视通晓全局,精准分析定位问题

↑ 点击预约“融云北极星”直播↑ 点击预约“实时社区”直播 近期,融云“北极星”数据系统完成功能迭代,新模块“数据监控平台”正式“履新上任”。关注【融云全球互联网通信云】了解更多 点击图片查看更多详情 此前,“北极星”系统主要为客…

水声功率放大器的作用是什么

水声功率放大器是一种专门用于水声设备的高功率电子设备,主要用于提升水下信号的传输距离和保证语音清晰度。它的作用在水下通信、水下测量、海洋科学等领域都非常重要。 其主要作用有以下几个方面: 增强信号传输距离 水声信号在水中传播会受到各种因素的…

有哪些好用的远程传输大文件的软件

随着网络技术的日益进步和普及,大文件远程传输已经成为了人们生活和工作中必不可少的一部分。然而,在远程传输大文件的过程中,经常会遇到传输速度慢、容易受到干扰等问题,因此需要一款高效、稳定、安全的大文件远程传输软件来解决…

离线安装docker

目录 1、下载docker 安装包 2、上传docker 到服务器目录/opt/ 3、解压docker-19.03.9.tgz 4、解压的docker文件夹全部移动至/usr/bin目录 5、将docker注册为系统服务 6、重启生效 6.1、重新加载配置文件 6.2、启动Docker服务 6.3、查看启动状态 ​6.4、 设置docker为开…

伦敦金分析时切勿过分自信

伦敦金价格会呈趋势变动,这是投资者进行技术分析最根本、最核心的因素。根据物理学上的动力法则,趋势的运行会延续,直到有反转的现象产生为止。事实上,虽然伦敦金的价格不断上下波动,但终究是朝一定的方向前进的&#…

数组

数组: 数字组成的组,组里即可以,int类型,string,字符串,数组当中的数据类型,可以由用户自定义 同一种,也可以是不同的数据类型组成的元素集合 数组最大的作用,可以一次…

JVM系列(5)——类加载过程

一、类的生命周期 加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using&#xff09…

在ICC/ICC2/FC中运行Calibre

1. which calibre找到calibre的安装目录 > which calibre > /eda/mentor/ixl_cal_version/bin/calibre 2. 在 /eda/mentor/ixl_cal_version目录下使用find ./* -name "icc_calibre.tcl",找到icc_calibre.tcl 3. 打开icc_calibre.tcl里面有不同工具(ICC2/FC/…

uniapp 封装公共方法(无需每个页面引用,直接调用)

封装方法: 1. 在根目录下建立common文件夹 创建com.js 2.在main.js中挂载(写在定义vue之后) import $com from /common/com.js Vue.prototype.$com $com 3.在com.js中按照以下格式定义方法 export default {//定义需要的方法 } 4.使用 click"$com.已经定义的方法名&q…

Java 装箱拆箱原理 包装类型缓存池

JAVA中的基本数据类型 byteshortintlongfloatdoublebooleanchar 为了让上述基本数据类型可以转为对象,Java在1.5推出了一系列包装类,基本类和包装类互相转换的过程,称为装箱和拆箱 缓存池 缓存池也叫常量池。它是事先存储一些常量数据用以…

openvpnas安装,可视化远程连接控制

本次安装环境为 centos7.9 本次安装软件为 openvpnas, 默认是两个连接授权,可以通过代码注入实现多连接授权 1.基础环境以及Python36安装 yum install python36 python36-devel wget -y 2.安装 openvpnas 1.在线安装 yum -y install https://as-repository.openv…

LeetCode 790. 多米诺和托米诺平铺 - 二维空间的动态规划

多米诺和托米诺平铺 中等 304 相关企业 有两种形状的瓷砖:一种是 2 x 1 的多米诺形,另一种是形如 “L” 的托米诺形。两种形状都可以旋转。 给定整数 n ,返回可以平铺 2 x n 的面板的方法的数量。返回对 109 7 取模 的值。 平铺指的是每个…

ES6的类 vs TypeScript的类:解密两种语言中的面向对象之争

文章目录 ES6 类ES6 类的常见特性1. 构造函数2. 实例方法3. 静态方法4. 继承 TypeScript 类TypeScript 类的特性1. 类型注解2. 访问修饰符3. 类型推断4. 接口实现 ES6 类 ES6(ECMAScript 2015)引入了类的概念,为 JavaScript 增加了面向对象编…

【2023 年第二届钉钉杯大学生大数据挑战赛】 初赛 B:美国纽约公共自行车使用量预测分析 问题一Python代码分析

2023 年第二届钉钉杯大学生大数据挑战赛 初赛 B:美国纽约公共自行车使用量预测分析 问题一 1 题目 Citi Bike是纽约市在2013年启动的一项自行车共享出行计划,由“花旗银行”(Citi Bank)赞助并取名为“花旗单车”(Citi Bike)。在曼哈顿,布鲁克…

PDF在线转PPT,不用下载软件网页在线即可转换!

PDF是我们经常在办公中使用的文件格式,它的兼容性和安全性使得它成为了传输文件的首选。而PPT则是我们常用的演示文稿格式,无论是在学校还是在公司,我们都需要制作演讲和汇报的PPT文件。由于这两种文件格式的重要性,我们经常需要进…

Vue+axios 使用CancelToken多次发送请求取消前面所有正在pendding的请求

需求: 项目中 折线图数据是循环调用的,此时勾选一个设备, 会出现多条线。 原因 折线图数据一进来接口循环在调用,勾选设备时,循环调用的接口有的处于pedding状态 ,有的还在加载中,这就导致勾…