Redis事务的理解与使用

news2025/1/16 1:38:50

文章目录

  • Redis 事务
    • 1)基本认识
    • 2)事务操作
      • 1.MULTI
      • 2.EXEC
      • 3.错误处理
      • 4.DISCARD
      • 5.WATCH
      • 6.SCRIPT

Redis 事务

官方文档,永远是你学习的第一手资料:Redis 事务

1)基本认识

 谈到事务,大家首先都会联想到 mysql 中复杂但又功能强大的“事务”,和 mysql 相比,redis 所提供的事务简直就是个“弟弟”。我们从 mysql 事务的四大基本特点进行比较:

原子性:

 原子性最初的含义就是把多个操作打包到一起,要么全部执行,要么全部不执行。但是mysql 在原子性这条道路上走的更远,它要求多个操作要么全部执行成功,要么全部不执行,如果其中任一操作执行失败,都会 rollback 确保数据的一致性。

 Redis 事务可以说具有原子性,也可以说没有,这是一个理解角度的问题。Redis 事务确实可以将多个操作打包一起执行,从这方面谈,Redis 是具有原子性的;但是和 mysql 不同,Redis 事务并不保证所有命令执行成功,由于 mysql 的标杆作用“拉高”了原子性的标准,从这一方面说,Redis 并不具有原子性。

 早些版本的 Redis 官网中明确提出了, Redis 事务具有原子性,但现在去看,官网已经把第一句删掉了。看连 Redis 官方都 “怂了”,所以我们还是倾向于认为 Redis 不具有原子性

image-20231121200726156

 那为什么 Redis 不提供和 mysql 一样强大的事务机制呢?首先 mysql 为了实现事务机制付出了巨大的代价,而 Redis 则是主打一个轻量简单,如果和 mysql 一样就丢了自己的特色,那又怎么从这么多数据库中冲杀出来呢?

一致性:

 由于 Redis 并不提供事务回滚机制,当其中某些操作失败时就会造成数据不一致的问题。例如以下这个场景:张三给李四转账 1000 元。张三余额 -1000 的操作成功,但是李四余额 + 1000 的操作失败,而 redis 并不会因为操作执行失败而回滚数据,从而导致数据不一致的问题发生

持久性:

 mysql 中又 redo log 保证事务的持久性,但是 redis 事务本身并不具有持久性,持久化还得依赖redis的 rdb 或者 aof 机制。但是否开启持久化,是redis-server自己的决定,和事务本身无关

隔离性:

 Redis 没有也不需要隔离性。隔离性是针对并发读写的问题而引入了,而 Redis 是一个单进程的数据库,不存在这方面的烦恼。

2)事务操作

1.MULTI

  • multi 指令用于开启一个事务

    127.0.0.1:6379> multi
    OK
    
  • Redis 服务端为每一个客户端维护一个事务命令队列,multi 后所有命令(除了 exec)都会被添加到队列中而不是立即执行(queued 状态)

    127.0.0.1:6379> set key1 1
    QUEUED
    127.0.0.1:6379> set key1 2
    QUEUED
    

2.EXEC

  • exec 指令用于按次序一次性执行事务队列中命令

    127.0.0.1:6379> exec
    1) OK
    2) OK
    127.0.0.1:6379> get key1
    "1"
    

3.错误处理

在 Redis 事务中存在两种类型的错误:

  • 在调用 exec 前发生错误,例如某个指令中存在语法错误。当这种错误发生时,整个事务都会被直接丢弃

    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> get key1
    QUEUED
    127.0.0.1:6379> abc
    (error) ERR unknown command `abc`, with args beginning with: 
    127.0.0.1:6379> exec
    (error) EXECABORT Transaction discarded because of previous errors.
    
  • 在调用 exec 期间发生的错误。在这种情况下,Redis 会继续执行剩余的命令,不管某些命令是否失败。

    127.0.0.1:6379> FLUSHALL
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> set key1 1
    QUEUED
    127.0.0.1:6379> LPOP key1
    QUEUED
    127.0.0.1:6379> set key2 2
    QUEUED
    127.0.0.1:6379> get key2
    QUEUED
    127.0.0.1:6379> EXEC
    1) OK
    2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
    3) OK
    4) "2"
    

    上面的案例也验证了 Redis 事务只能保证多条一起执行,但并不保证所有的命令都会执行成功。失败了也不会数据回滚,因而存在一致性的问题

4.DISCARD

  • discard 指令用于终止取消当前正在执行的事务,队列中的所有指令都会被直接丢弃

    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> get key1
    QUEUED
    127.0.0.1:6379> get key2
    QUEUED
    127.0.0.1:6379> discard
    OK
    127.0.0.1:6379> exec
    (error) ERR EXEC without MULTI
    
  • 当前没有正在执行的事务,则 discard 指令无效

    127.0.0.1:6379> discard
    (error) ERR DISCARD without MULTI
    

5.WATCH

用法:

  • 在执行事务期间,某个键值被其他客户端修改了,其结果就容易令人产生歧义,例如下面这个场景

    timeclient_1client_2
    t1execute command multi
    t2execute command set key1 1
    ……
    t3execute command set key1 2
    t4execute command exec
  • watch 与事务配合使用,它允许你监视多个 key,如果在事务的执行期间任何一个键被其他客户端修改,都会导致当前事务全部丢弃,从而确保了事务执行期间数据的一致性。watch 的作用时间从 multi 开始到执行 exec 结束。

    // client1
    127.0.0.1:6379> mset key1 1 key2 2
    OK
    127.0.0.1:6379> watch key1 key2
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> mget key1 key2
    QUEUED
    127.0.0.1:6379> exec 
    (nil)    // 事务执行失败
    
    // client2:在client1事务执行期间进行如下修改
    127.0.0.1:6379> incr key1
    (integer) 2
    127.0.0.1:6379> decr key2
    (integer) 1
    
  • unwatch 的作用与 watch 相反,它用于清除对所有 key 的 “watch”。在执行 exec 或者 client 退出时,所有的 key 都会 “unwatched”

原理:

 watch 本质就是一把乐观锁,通过CAS机制实现:每个 "watched " 变量都有一个初始版本号,修改变量会让其版本号变大,在执行 exec 时会比较当前版本号与 watch 时的版本号是否一致,如果不一致,说明变量在事务执行期间发生了修改,当前事务就会被 discard

案例:

下面是官方文档提供的一个使用案例,通过 watch 去创造一个新的原子操作:

WATCH zset
element = ZRANGE zset 0 0
MULTI
ZREM zset element
EXEC

 从 zset 中删除一个元素有两部:1)找到最小的元素 2) 将最小的元素删除。如果删除失败,说明最小值被其他客户端修改,那么我们就重复上面操作,直到删除一个最小值

6.SCRIPT

 任何 redis 事务能完成的操作,我们都可以使用 redis script 完成。redis script 天生就有把多个指令打包执行的能力,感兴趣的可以去网上找找 lua 脚本操作 redis 的教程

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于element-plus定义表单配置化扩展表单按钮

文章目录 前言一、新增btn.vue组件二、使用总结如有启发&#xff0c;可点赞收藏哟~ 前言 在后台管理系统一般都存在列表查询&#xff0c;且可输入数据进行查询 基于element-plus定义表单配置化 新增按钮配置化 一、新增btn.vue组件 <template><template v-for&qu…

如何做好性能压测?压测环境设计和搭建的7个步骤你知道吗?

简介&#xff1a;一般来说&#xff0c;保证执行性能压测的环境和生产环境高度一致是执行一次有效性能压测的首要原则。有时候&#xff0c;即便是压测环境和生产环境有很细微的差别&#xff0c;都有可能导致整个压测活动评测出来的结果不准确。 1. 性能环境要考虑的要素 1.1 系…

5种社交媒体策略提升你的SEO

你希望你的网站在多大程度上在搜索结果中被更多的受众看到&#xff1f;如果你想增加你网站的曝光率和流量&#xff0c;社交媒体整合是提高你的SEO的一个好方法。为了帮助公司和网站所有者提高他们的搜索引擎优化 &#xff08;SEO&#xff09;&#xff0c;这篇文章将介绍五种社交…

易点易动设备管理系统:提升企业设备保养效率的最佳选择

在现代企业中&#xff0c;设备的正常运行和保养对于业务的顺利进行至关重要。然而&#xff0c;传统的手动设备管理方式往往效率低下、容易出错&#xff0c;给企业带来不必要的成本和风险。为了解决这一问题&#xff0c;易点易动设备管理系统应运而生。本文将介绍易点易动设备管…

ansible的基本安装

目录 一、简介 1.ansible自动化运维人工运维时代 2.自动化运维时代 3.ansible介绍 4.ansible特点 二、ansible实践 1.环境 2.ansible管理安装 3.ansible被管理安装 4.管理方式 5.添加被管理机器的ip 6.ssh密码认证方式管理 三、配置免密登录 1.ansible自带的密码…

2021年12月 Scratch(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 舞台上有3个角色,小猫的程序如下图所示,另外两个角色没有程序。点击绿旗,下列选项正确的是? A:小猫随鼠标移动,可能会遮挡其他两个角色 B:小猫随鼠标移动,可能会被其他两个…

前缀和的动态维护——树状数组[C/C++]

文章目录 前言lowbitlowbit的定义lowbit的计算 树状数组的思想树状数组的操作单点修改 update前缀查询 query树状数组的建立 build 前言 树状数组巧妙了利用位运算和树形结构实现了允许单点修改的情况下&#xff0c;动态维护前缀和&#xff0c;并且实现单点修改和前缀和查询的效…

2021年09月 Scratch(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 执行下图所示程序,舞台上的角色? A:在1秒内滑行到随机位置 B:不断地重复滑行到随机位置 C:只有按下空格键的时候,才会滑行到随机位置 D:只有按下空格键以外键的时候,才会滑行…

【鸿蒙应用ArkTS开发系列】- 云开发入门实战一使用鸿蒙登录组件实现客户端登录

目录 概述使用云端一体化开发模板创建项目工程创建登录入口页面集成登录SDK组件依赖登录组件SDK使用登录组件SDK 开启“手机号码”和“邮箱地址”认证方式 概述 通过本次课程&#xff0c;我们将学习怎么使用云端一体化开发模板来创建云开发工程&#xff0c;以及如何使用鸿蒙登…

机器学习第12天:聚类

文章目录 机器学习专栏 无监督学习介绍 聚类 K-Means 使用方法 实例演示 代码解析 绘制决策边界 本章总结 机器学习专栏 机器学习_Nowl的博客-CSDN博客 无监督学习介绍 某位著名计算机科学家有句话&#xff1a;“如果智能是蛋糕&#xff0c;无监督学习将是蛋糕本体&a…

Deepmind开发音频模型Lyria 用于生成高品质音乐;创建亚马逊新产品评论摘要

&#x1f989; AI新闻 &#x1f680; Deepmind开发音频模型Lyria 用于生成高品质音乐 摘要&#xff1a;Deepmind推出名为Lyria的音频模型&#xff0c;可生成带有乐器和人声的高品质音乐。Lyria模型针对音乐生成的挑战&#xff0c;解决了音乐信息密度高、音乐序列中的连续性维…

智能驾驶产品开发中如何贯彻“正向开发”理念

摘要&#xff1a; 基于演绎法的正向开发理念&#xff0c;能够让智能驾驶产品在充分满足用户需求&#xff0c;保证产品质量的同时&#xff0c;确保开发目标合理且得到落实。 前段时间&#xff0c;微博CEO吐槽理想L9智能驾驶“行驶轨迹不居中”&#xff0c;在网上引发了热烈讨论…

Youtube运营如何打破0播放?你需要的技巧、策略与工具

对于有跨境意向的内容创作者或者品牌企业来说&#xff0c;YouTube是因其巨大的潜在受众群和商业价值成为最值得投入变现与营销计划的平台。 据统计&#xff0c;98% 的美国人每月访问 YouTube&#xff0c;近三分之二的人每天访问。但是&#xff0c;YouTube还远未达到过度饱和的…

Android APN 参数数据库设计和代码实现

Android U 网页代码&#xff1a;/ - OpenGrok cross reference for / (aospxref.com) 字段参数介绍 实体对象 ApnSetting ApnSetting.java - OpenGrok cross reference for /frameworks/base/telephony/java/android/telephony/data/ApnSetting.java (aospxref.com) An Acc…

你不知道的库:库的种类,作用和加载方式

你不知道的库&#xff1a;库的种类&#xff0c;作用和加载方式 &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客…

Linux 局域网传输工具LANDrop安装

Linux 局域网传输工具LANDrop安装 &#x1f959;下载&#x1f32d;解压&#x1f96a;运行 &#x1f959;下载 官网下载 或网盘 &#x1f32d;解压 使用以下命令解压获得squashfs-root文件夹 ./LANDrop-latest-linux.AppImage --appimage-extract&#x1f96a;运行 进入squ…

分布式锁3: zk实现分布式锁

一 zk 实现分布式锁 1.1 zk分布式操作命令 1.指令&#xff1a; ls / get /zookeeper create /aa "test" delete /aa set /aa "test1" 2..znode节点类型&#xff1a; 永久节点&#xff1a;create /pa…

028 - STM32学习笔记 - ADC结构体学习(二)

028 - STM32学习笔记 - 结构体学习&#xff08;二&#xff09; 上节对ADC基础知识进行了学习&#xff0c;这节在了解一下ADC相关的结构体。 一、ADC初始化结构体 在标准库函数中基本上对于外设都有一个初始化结构体xx_InitTypeDef&#xff08;其中xx为外设名&#xff0c;例如…

从mysql源码编译出相应的库和可执行文件及搭建mysql服务端

目录 1. 问题的提出 2. 源码下载 3. 升级或安装某些前置软件 3.1. 升级CMake 3.2. 升级gcc、g 4. 安装依赖库 4.1. 安装OpenSSL 4.2. 安装Curses 4.3. 安装pkg-config 5. 编译、安装 6. 编译结果、配置 7. 编译错误处理 7.1. 错误1 7.2. 错误2 8. 搭建mysql数…

FindMy技术用于充电宝

充电宝是一种便捷的充电器&#xff0c;方便个人随身携带&#xff0c;能够自行储备电能&#xff0c;为主流电子设备提供充电服务。它广泛应用于没有外部电源供应的场所&#xff0c;例如旅行、户外活动或紧急情况下&#xff0c;为用户的手持设备提供持续的电力支持&#xff0c;确…