Redis入门第三步:Redis事务处理

在这里插入图片描述

欢迎继续跟随《Redis新手指南:从入门到精通》专栏的步伐!在本文中,我们将探讨Redis的事务处理机制。了解如何使用事务来保证一系列操作的原子性和一致性,这对于构建可靠的应用程序至关重要

1 什么是Redis事务🍀

​ Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序列化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中

总结说:redis 事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令

2 Redis事务相关命令和使用🍀

MULTI、EXEC、DISCARD 和 WATCH 是 Redis 事务相关的命令

  • MULTI :开启事务,redis会将后续的命令逐个放入队列中,然后使用EXEC命令来原子化执行这个命令系列

    原子化执行,它们要么全部执行成功,要么全部回滚。

  • EXEC:执行事务中的所有操作命令

  • DISCARD:取消事务,放弃执行事务块中的所有命令

  • WATCH:监视一个或多个key,如果事务在执行前,这个key(或多个key)被其他命令修改,则事务被中断,不会执行事务中的任何命令

  • UNWATCH:取消WATCH对所有key的监视

1.标准的事务执行

给k1、k2分别赋值,在事务中修改k1、k2,执行事务后,查看k1、k2值都被修改

127.0.0.1:6379[1]> set key1 value1
OK
127.0.0.1:6379[1]> set key2 value2
OK
127.0.0.1:6379[1]> multi # 开启事务
OK
127.0.0.1:6379[1](TX)> set key1 11
QUEUED
127.0.0.1:6379[1](TX)> set key2 22
QUEUED
127.0.0.1:6379[1](TX)> exec # 执行事务中所有的操作命令
1) OK
2) OK
127.0.0.1:6379[1]> get key1
"11"
127.0.0.1:6379[1]> get key2
"22"
2.事务取消
127.0.0.1:6379[1]> multi
OK
127.0.0.1:6379[1](TX)> set key1 111
QUEUED
127.0.0.1:6379[1](TX)> set key2 222
QUEUED
127.0.0.1:6379[1](TX)> DISCARD # 取消事务
OK
127.0.0.1:6379[1]> exec
(error) ERR EXEC without MULTI
3.事务出现错误的处理
  • 语法错误(编译器错误)

在开启事务后,修改k1值为11,k2值为22,但k2语法错误,最终导致事务提交失败,k1、k2保留原值

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 11
QUEUED
127.0.0.1:6379> sets k2 22
(error) ERR unknown command `sets`, with args beginning with: `k2`, `22`, 
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379>
  • Redis类型错误(运行时错误)

​ 在开启事务后,修改k1值为11,k2值为22,但将k2的类型作为List,在运行时检测类型错误,最终导致事务提交失败,此时事务并没有回滚,而是跳过错误命令继续执行, 结果k1值改变、k2保留原值

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k1 v2
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 11
QUEUED
127.0.0.1:6379> lpush k2 22
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> get k1
"11"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379>

3 CAS操作实现乐观锁🍀

WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为

  • CAS? 乐观锁?Redis官方的例子帮你理解

被 WATCH 的键会被监视,并会发觉这些键是否被改动过了。如果有至少一个被监视的键在 EXEC 执行之前被修改了, 那么整个事务都会被取消, EXEC 返回nil-reply来表示事务已经失败。

举个例子, 假设我们需要原子性地为某个值进行增 1 操作(假设 INCR 不存在)。

首先我们可能会这样做:

val = GET mykey
val = val + 1
SET mykey $val

上面的这个实现在只有一个客户端的时候可以执行得很好。但是, 当多个客户端同时对同一个键进行这样的操作时, 就会产生竞争条件。举个例子, 如果客户端 A 和 B 都读取了键原来的值, 比如 10 , 那么两个客户端都会将键的值设为 11 , 但正确的结果应该是 12 才对。

有了 WATCH ,我们就可以轻松地解决这类问题了:

WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC

使用上面的代码, 如果在 WATCH 执行之后, EXEC 执行之前, 有其他客户端修改了 mykey 的值, 那么当前客户端的事务就会失败。程序需要做的, 就是不断重试这个操作, 直到没有发生碰撞为止。

这种形式的锁被称作乐观锁, 它是一种非常强大的锁机制。并且因为大多数情况下, 不同的客户端会访问不同的键, 碰撞的情况一般都很少, 所以通常并不需要进行重试。

  • watch是如何监视实现的呢

Redis使用WATCH命令来决定事务是继续执行还是回滚,那就需要在MULTI之前使用WATCH来监控某些键值对,然后使用MULTI命令来开启事务,执行对数据结构操作的各种命令,此时这些命令入队列。

当使用EXEC执行事务时,首先会比对WATCH所监控的键值对,如果没发生改变,它会执行事务队列中的命令,提交事务;如果发生变化,将不会执行事务中的任何命令,同时事务回滚。当然无论是否回滚,Redis都会取消执行事务前的WATCH命令

  • watch 命令实现监视

在事务开始前用WATCH监控k1,之后修改k1为11,说明事务开始前k1值被改变,MULTI开始事务,修改k1值为12,k2为22,执行EXEC,发回nil,说明事务回滚;查看下k1、k2的值都没有被事务中的命令所改变。

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> WATCH k1
OK
127.0.0.1:6379> set k1 11
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 12
QUEUED
127.0.0.1:6379> set k2 22
QUEUED
127.0.0.1:6379> EXEC
(nil)
127.0.0.1:6379> get k1
"11"
127.0.0.1:6379> get k2
"v2"
  • UNWATCH取消监视
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> WATCH k1
OK
127.0.0.1:6379> set k1 11
OK
127.0.0.1:6379> UNWATCH
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 12
QUEUED
127.0.0.1:6379> set k2 22
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
127.0.0.1:6379> get k1
"12"
127.0.0.1:6379> get k2
"22"
127.0.0.1:6379>

4 Redis事务执行步骤🍀

通过上文命令执行,很显然Redis事务执行是三个阶段:

  • 开启:以MULTI开始一个事务
  • 入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面
  • 执行:由EXEC命令触发事务

当一个客户端切换到事务状态之后, 服务器会根据这个客户端发来的不同命令执行不同的操作:

  • 如果客户端发送的命令为 EXEC 、 DISCARD 、 WATCH 、 MULTI 四个命令的其中一个, 那么服务器立即执行这个命令。
  • 与此相反, 如果客户端发送的命令是 EXEC 、 DISCARD 、 WATCH 、 MULTI 四个命令以外的其他命令, 那么服务器并不立即执行这个命令, 而是将这个命令放入一个事务队列里面, 然后向客户端返回 QUEUED 回复。

更深入的理解

我们再通过几个问题来深入理解Redis事务。

为什么 Redis 不支持回滚?

如果你有使用关系式数据库的经验,那么“Redis 在事务失败时不进行回滚,而是继续执行余下的命令”这种做法可能会让你觉得有点奇怪。

以下是这种做法的优点:

  • Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
  • 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。

有种观点认为 Redis 处理事务的做法会产生 bug , 然而需要注意的是, 在通常情况下, 回滚并不能解决编程错误带来的问题。举个例子, 如果你本来想通过 INCR 命令将键的值加上 1 , 却不小心加上了 2 , 又或者对错误类型的键执行了 INCR , 回滚是没有办法处理这些情况的。

如何理解Redis与事务的ACID?

一般来说,事务有四个性质称为ACID,分别是原子性,一致性,隔离性和持久性

  • 原子性atomicity

    # 首先通过上文知道 运行期的错误是不会回滚的,很多文章由此说Redis事务违背原子性的;而官方文档认为是遵从原子性的。Redis官方文档给的理解是,**Redis的事务是原子性的:所有的命令,要么全部执行,要么全部不执行**。而不是完全成功
    
  • 一致性consistency

    #  redis事务可以保证命令失败的情况下得以回滚,数据能恢复到没有执行之前的样子,是保证一致性的,除非redis进程意外终结
    
  • 隔离性Isolation

    #  redis事务是严格遵守隔离性的,原因是redis是单进程单线程模式(v6.0之前),可以保证命令执行过程中不会被其他客户端命令打断.但是,Redis不像其它结构化数据库有隔离级别这种设计
    
  • 持久性Durability

    #  **redis事务是不保证持久性的**,这是因为redis持久化策略中不管是RDB还是AOF都是异步执行的,不保证持久性是出于对性能的考虑
    

5 Redis事务其它实现🍀

  • 基于Lua脚本,Redis可以保证脚本内的命令一次性、按顺序地执行,其同时也不提供事务运行错误的回滚,执行过程中如果部分命令运行错误,剩下的命令还是会继续运行完
  • 基于中间标记变量,通过另外的标记变量来标识事务是否执行完成,读取数据时先读取该标记变量判断是否事务执行完成。但这样会需要额外写代码实现,比较繁琐

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解锁数据宝藏:AI驱动搜索工具,让非结构化数据“说话

哈哈,说起这个 AI 搜索演示啊,那可真是个有意思的话题!非结构化数据,这家伙虽然难搞,但价值却是杠杠的。今天呢,咱就好好聊聊怎么借助 Fivetran 和 Milvus,快速搭建一个 AI 驱动的搜索工具,让企业能从那些乱七八糟的数据里淘到金子! 一、非结构化数据的挑战与机遇 首…

堆【数据结构C语言版】【 详解】

目录-笔记整理 一、思考二、堆概念与性质三、堆的构建、删除、添加1. 构建2. 删除3. 添加 四、复杂度分析4.1 时间复杂度4.2 空间复杂度 五、总结 一、思考 设计一种数据结构,来存放整数,要求三个接口: 1)获取序列中的最值&#…

Thinkphp/Laravel旅游景区预约系统的设计与实现

目录 技术栈和环境说明具体实现截图设计思路关键技术课题的重点和难点:框架介绍数据访问方式PHP核心代码部分展示代码目录结构解析系统测试详细视频演示源码获取 技术栈和环境说明 采用PHP语言开发,开发环境为phpstudy 开发工具notepad并使用MYSQL数据库…

景联文科技入选《2024中国AI大模型产业图谱2.0版》数据集代表厂商

近日,大数据产业领域头部媒体数据猿携手上海大数据联盟联合发布了备受瞩目的《2024中国AI大模型产业图谱2.0版》。以大数据与AI为代表的智能技术为主要视角,聚焦全产业链,为业内提供更为专业直观的行业指导。 景联文科技凭借高质量数据集&…

基于大数据的学生体质健康信息系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…

Vue Mini基于 Vue 3 的小程序框架

新的小程序框架 https://vuemini.org/ Vue Mini 是一个基于 Vue 3 的小程序框架,它允许开发者利用 Vue 3 的强大功能来构建微信小程序。Vue Mini 的核心优势在于它的响应式系统和组合式 API,这些特性让开发者能够以一种更声明式、更高效的方式来编写和…

江科大笔记——新建工程

STM32的开发方式 目前STM32的开发方式主要有基于寄存器的方式、基于标准库的方式(库函数的方式)、基于HAL库的方式: 基于库函数的方式是使用ST官方提供的封装好的函数,通过调用这些函数来间接地配置寄存器。基于HAL库的方式可以…

【机器学习(七)】分类和回归任务-K-近邻 (KNN)算法-Sentosa_DSML社区版

文章目录 一、算法概念二、算法原理(一)K值选择(二)距离度量1、欧式距离2、曼哈顿距离3、闵可夫斯基距离 (三)决策规则1、分类决策规则2、回归决策规则 三、算法优缺点优点缺点 四、KNN分类任务实现对比&am…

【CKA】二、节点管理-设置节点不可用

2、节点管理-设置节点不可用 1. 考题内容: 2. 答题思路: 先设置节点不可用,然后驱逐节点上的pod 这道题就两条命令,直接背熟就行。 也可以查看帮助 kubectl cordon -h kubectl drain -h 参数详情: –delete-empty…

【COSMO-SkyMed系列的4颗卫星主要用途】

COSMO-SkyMed系列的4颗卫星主要用于提供一个多用途的对地观测平台,服务于民间、公共机构、军事和商业领域。以下是这4颗卫星的主要用途: 民防与环境风险管理: 卫星的高分辨率雷达图像可用于监测自然灾害,如地震、洪水、滑坡等&am…

【计算机网络】网络层详解

文章目录 一、引言二、IP 基础知识1、IP 地址2、路由3、IP报文4、IP报文的分片与重组 三、IP 属于面向无连接型四、IP协议相关技术1、DNS2、ICMP3、NAT技术4、DHCP 一、引言 TCP/IP的心脏是网络层。这一层主要由 IP 和 ICMP 两个协议组成。网络层的主要作用是“实现终端节点之…

Redis进阶篇 - 缓存穿透、缓存击穿、缓存雪崩问题及其解决方案

文章目录 1 文章概述2 缓存穿透2.1 什么是缓存穿透?2.2 缓存穿透的解决方法2.2.1 做好参数校验2.2.2 缓存无效Key2.2.3 使用布隆过滤器2.2.4 接口限流 3 缓存击穿3.1 什么是缓存击穿?3.2 缓存击穿的解决方法3.2.1 调整热点数据过期时间3.2.2 热点数据预热…

Postgresql怎么查询数据库中所有的表,odoo17数据库最依赖表整理

今天遇到了一个需求,需要梳理odoo中数据库表的分类,所以想要知道怎么查询当前数据库中所有的表,特此记录. 一个简单的SQL语句: select * from pg_tables;得到的结果如下: 显然这个有点杂乱,我们换一个SQL语句: select tablename from pg_tables where schemanamepublic不过…

软件测试学习笔记丨Mock的价值与实战

本文转自测试人社区,原文链接:https://ceshiren.com/t/topic/32331 一、Mock的价值与意义 1.1 简介 测试过程中,对于一些不容易构造或获取的对象,用一个虚拟的对象来替代它,达到相同的效果,这个虚拟的对象…

启动服务并登录MySQL9数据库

【图书推荐】《MySQL 9从入门到性能优化(视频教学版)》-CSDN博客 《MySQL 9从入门到性能优化(视频教学版)(数据库技术丛书)》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) Windows平台下安装与配置MyS…

Activiti 工作流大致了解

一、什么是 Activiti 简而言之&#xff0c;就是系统的流程图&#xff0c;如&#xff1a;请假审批流程、账单审批流程等。 二、mysql与pom配置 mysql要使用jdbc:mysql://localhost:3306/activiti?autoReconnecttrue pom文件要添加关键依赖 <!--activiti核心依赖--> &…

makefile和CMakeLists/C++包管理器

make 大家可能会很奇怪&#xff0c;都什么年代了&#xff0c;还学makefile&#xff0c;cmake都有些过时了&#xff0c;为什么还要再学这个呢&#xff1f; 我是这么看待这个问题的&#xff0c;cmake跨平台性还是很有有优势的&#xff0c;有着多年积累的底蕴&#xff0c;借助大模…

IDE 使用技巧与插件推荐全面指南

目录 目录 常用IDE概述 Visual Studio Visual Studio Code IntelliJ IDEA PyCharm Eclipse IDE 使用技巧 通用技巧 Visual Studio 专属技巧 Visual Studio Code 专属技巧 IntelliJ IDEA 专属技巧 插件推荐 Visual Studio 插件 Visual Studio Code 插件 IntelliJ…

STM32 实现 UDP 广播通信

目录 一、引言 二、准备工作 1.硬件准备 2.软件准备 三、LWIP 协议栈的配置与初始化 1.添加 LWIP 源文件 2.配置 LWIP 3.初始化 LWIP 四.创建 UDP 广播套接字 1.创建 UDP 控制块 2.绑定本地端口 五、设置 UDP 广播选项 1.设置广播地址 2.设置广播选项 六、发…

防反接电路设计

方案1 串联二极管&#xff0c; 优点&#xff1a;成本低、设计简单 缺点&#xff1a;损耗大&#xff0c;P ui 方案2 串联自恢复保险丝 当电源反接的时候&#xff0c;D4导通&#xff0c;F2超过跳闸带你留&#xff0c;就会断开&#xff0c;从而保护了后级电路 方案3 H桥电路…