聊一聊Redis事务

没错,Redis也有事务管理,但是功能很简单,在正式开发中也并不推荐使用。但是面试中有可能会问到,所以本文简单谈一谈Redis的事务。

通过这篇文章,你会了解

  • Redis为什么要提供事务?
  • Redis事务基本指令和使用方法
  • CAS乐观锁是什么?
  • Redis事务为什么不支持回滚?

1. 为什么要用事务

我们知道Redis的单个命令是原子性的,比如 getsetmgetmset等指令。

原子性是指操作是不可分割的,在执行完毕之前不会被任何其它任务或事件中断,也就不会有并发的安全性问题

在涉及到多个命令的时候,如果需要把多个命令设置为一个不可分割的处理序列,就需要用到事务了。

比如,招财和陀螺各有100元,招财给陀螺转了10元,这时候需要在Redis中把招财的金额总数-10,同时需要把陀螺的金额总数+10。这两个操作要么同时成功,要么同时失败,这时候就需要事务了。

实际上,Redis连这个简单的需求都没办法完美做到,至于为啥,接着往下看吧

2. 事务的用法

2.1 5个基本指令

Redis提供了以下5个基本指令,先混个眼熟就行,接下来在案例中进行实操,想记不住都难

命令 格式 作用 返回值 MULTI MULTI 显式开启Redis事务,后续命令将排队,等候使用EXEC进行原子执行 always OK. EXEC EXEC 执行事务中的 commands

队列,恢复连接状态。如果 WATCH

在之前被调用,只有监测中的 Keys

没有被修改,命令才会被执行,否则停止执行(详见下文, CAS

机制)
成功:

返回数组 —— 每个元素对应着原子事务中一个 command

的返回结果;

失败:

返回 NULL Ruby

返回 nil

); DISCARD DISCARD 清除事务中的 commands

队列,恢复连接状态。如果 WATCH

在之前被调用,释放监测中的 Keys

always OK. WATCH WATCH key [key …] 将给出的 Keys

标记为监测态,作为事务执行的条件 always OK. UNWATCH UNWATCH 清除事务中 Keys

的监测态,如果调用了 EXEC

或者 DISCARD

,则没有必要再手动调用 UNWATCH

always OK.

2.2 案例演示

案例场景:招财和陀螺各有100元,招财给陀螺转了10元,这时候需要在Redis中把招财的金额-10,同时需要把陀螺的金额+10。

2.2.1 事务提交

我们首先为陀螺和招财初始化自己的金额;然后使用 MULTI命令 显式开启Redis事务。 该命令总是直接返回OK。此时用户可以发送多个指令,Redis不会立刻执行这些命令,而是将这些指令 依次放入当前事务的指令队列中; EXEC被调用后,所有的命令才会被依次执行。

给陀螺初始化100元
127.0.0.1:6379> set tuoluo 100
OK
给招财初始化100元
127.0.0.1:6379> set zhaocai 100
OK
显式开启事务
127.0.0.1:6379> MULTI
OK
给陀螺增加10元
127.0.0.1:6379(TX)> INCRBY tuoluo 10
QUEUED
给招财减少10元
127.0.0.1:6379(TX)> DECRBY zhaocai 10
QUEUED
执行事务中的所有指令(提交事务)
127.0.0.1:6379(TX)> EXEC
1) (integer) 110
2) (integer) 90

2.2.2 嵌套事务

Redis不支持嵌套事务,多个 MULTI命令和单个 MULTI命令效果相同。

第一次开启事务
127.0.0.1:6379> MULTI
OK
尝试嵌套事务
127.0.0.1:6379(TX)> MULTI
(error) ERR MULTI calls can not be nested
仍然处于第一个事务当中
127.0.0.1:6379(TX)>

2.2.3 放弃事务

如果开启事务之后,中途后悔了怎么办?调用 DISCARD可以清空事务中的指令队列,退出事务。

127.0.0.1:6379> MULTI
OK
在事务中调用DISCARD指令
127.0.0.1:6379(TX)> DISCARD
OK
会退出当前事务
127.0.0.1:6379>

2.2.4 watch指令

假如我们在一个客户端连接中开启了事务,另一个客户端连接修改了这个事务涉及的变量值,将会怎样?

聊一聊Redis事务

client1开启了一个转账的事务,事务开始时招财和陀螺各自拥有100元,在执行 EXEC指令之前,client2将陀螺的余额添加了10元,此时执行 EXEC之后,陀螺最终的金额为120元,招财为90元。

很明显,这种情况下存在数据安全问题。

为此Redis提供了 WATCH的指令,该指令可以为Redis事务提供 CAS乐观锁行为,即多个连接同时更新变量的时候,会和变量的初始值进行比较,只在这个变量的值没有被修改的情况下才会更新成新的值。

2.2.4.1 WATCH用法

对应我们的案例,我们可以使用 WATCH监听一个或多个key,如果开启事务之前,至少有一个被监视的key在 EXEC执行之前被修改了,那么整个事务都会被取消,直接返回 nil(见下面的案例)。 UNWATCHWATCH的反操作。

聊一聊Redis事务

2.2.4.2 CAS机制

CAS(Compare And Swap)比较并替换,是多并发时常用的一种乐观锁技术

CAS需要三个变量信息,分别是内存位置(JAVA中的内存地址,V),旧的预期值(A)和新值(B)。CAS执行时,当且仅当V和预期值A相等时,更新V的值为新值B,否则不执行更新。

聊一聊Redis事务

3. 事务执行出错怎么办

事务执行时可能遇到问题,按照发生的时机不同分为两种:

  • 执行 EXEC之前
  • 执行 EXEC之后

3.1 执行EXEC之前发生错误

比如指令存在语法错误(参数数量不对,指令单词拼错)导致不能进入 commands队列,这一步主要是编译错误,还未到运行时。

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SET tuoluo
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379(TX)> EXEC
(error) EXECABORT Transaction discarded because of previous errors.

这种情况下事务会执行失败,队列中的所有指令都不会得到执行。

3.2 执行EXEC之后发生错误

这种错误往往是类型错误,比如对String使用了Hash的命令,这是运行时错误,编译期间不会出错

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SET tuoluo 100
QUEUED
127.0.0.1:6379(TX)> LPOP tuoluo
QUEUED
127.0.0.1:6379(TX)> EXEC
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value

我们发现, SET tuoluo 100的命令居然执行成功了,也就是在发生了运行时异常的情况下,错误的指令不会被执行,但是其他的命令不会受影响。

聊一聊Redis事务

这种方式显然不符合我们对 原子性的定义,也就是Redis的事务无法实现原子性,无法保证数据一致。

针对这种缺陷,Redis官方也是做了说明的。

4. Redis事务为什么不支持回滚

引自Redis 官方文档

聊一聊Redis事务

为了方便大家理解,我翻译一下就是:

你们程序员的锅,关我们Redis屁事儿!

Redis官方认为,只有在命令语法错误或者类型错误的时候,Redis命令才会执行失败。而且他们认为有这种错误的语法一般也不会进入到生产环境。而且不支持回滚可以使他们有更多时间玩儿Redis运行得更简单快捷。

这种说法多牛!如果出问题就是程序员的问题,写错了还让代码进入生产环境,那就是罪上加罪,你永远赖不着Redis官方。

这可能就是不推荐使用Redis事务的原因了吧,鸡肋是一方面,万一被官方打脸了呢?所以Redis事务的知识稍微了解一下就好,面试被问到能回到上来就可以了。

下期见!

5. 推荐阅读

Original: https://www.cnblogs.com/chanmufeng/p/15901201.html
Author: 蝉沐风
Title: 聊一聊Redis事务

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/711197/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 浅析Python中的asyncio

    asyncio理解 最近突然想了解一下Python的异步编程,于是乎就去了解了下asyncio的使用。借用官网的话 asyncio 是用来编写并发代码的库,使用 async/awa…

    技术杂谈 2023年7月23日
    069
  • UE4 Keynote 1

    【 UE4 Keynote 1】 1、U3D中的Project,在UE4中叫 ContentBrowser,中文名叫”内容浏览器” 最多可以打开4个Cont…

    技术杂谈 2023年5月31日
    085
  • Docker基本命令

    注意:删除镜像,正&amp…

    技术杂谈 2023年6月21日
    085
  • Mac下Charles踩坑记录

    初次使用Charles,摸索着抓包的过程中遇到了很多问题。在这里一一记录一下,避免其他初学者踩坑。 问题1:不显示request和response? 在Charles的配置页面可以…

    技术杂谈 2023年7月24日
    054
  • MongoDB排序时内存大小限制和创建索引的注意事项!

    线上服务的MongoDB中有一个很大的表,我查询时使用了 sort()根据某个字段进行排序,结果报了下面这个错误: [Error] Executor error during fi…

    技术杂谈 2023年7月24日
    068
  • ASP.NET CORE WEB项目介绍

    首先创建一个asp.net core web应用程序 第二步 目前官方预置了7种模板项目供我们选择。从中我们可以看出,既有我们熟悉的MVC、WebAPI,又新添加了Razor Pa…

    技术杂谈 2023年6月21日
    093
  • 用于排队叫号系统的redis工具类

    分析 排队叫号系统的队列数据变化很频繁,因此可以考虑使用redis的list结构存储某一队列的数据,与前端采用websocekt连接,后端主动推送数据给前端,避免频繁轮询造成资源浪…

    技术杂谈 2023年7月23日
    071
  • Vue 计算属性 和侦听器

    在模板内使用 表达式非常便利,但是这个目的是进行简单的运算。如果在模板中进行复杂的逻辑会让模板过重,且难以维护。 对于任何复杂的逻辑,应当使用 计算属性。 #基础例子 通过上面的例…

    技术杂谈 2023年7月11日
    077
  • OO第二单元总结

    OO第二单元电梯总结 OO第二单元电梯总结 架构模式 hw5 一级生产者消费者模型with策略类分离 关于策略类的提取: 关于优化实现了: hw6 增加了两个电梯子类的一级生产者消…

    技术杂谈 2023年7月25日
    065
  • 设计模式 23 访问者模式

    访问者模式(Visitor Pattern)属于 行为型模式 生活中经常会有这样的情况,同样的事物不同人有完全不同的感受,正所谓 一千个读者一千个哈姆雷特。 程序中也是一样,往往不…

    技术杂谈 2023年7月25日
    066
  • 一款开源的跨平台实时web应用框架——DotNetify

    今天给大家介绍一个开源的轻量级跨平台实时HTML+C#.NET Web应用程序开发框架——DotNetify,允许你在C#.NET后端上创建具有React、React Native…

    技术杂谈 2023年5月31日
    0114
  • Java8 Stream 的最佳实践

    java8stream提供了对于集合类的流失处理,其具有以下特点: Lazy Evaluation(长度可以无限) 只能使用一次 内部迭代 Lazy Evaluation类似函数式…

    技术杂谈 2023年7月24日
    055
  • SSM实战(56)在线教育(56)后端(25)课程管理(11)章节的小节的添加/删除

    博客园 :当前访问的博文已被密码保护 请输入阅读密码: Original: https://www.cnblogs.com/qiu-hua/p/16514631.htmlAutho…

    技术杂谈 2023年6月1日
    091
  • 架肩与拐肘

    内家拳大多讲究沉肩坠肘,太极拳也是,沉肩坠肘是费时功夫,成年人必须花一定的时间专门去纠正。沉肩坠肘解决不了,上肢的实战只能靠蛮力。 沉肩功夫出不来的人,力从地起的劲力很难直接自然性…

    技术杂谈 2023年5月31日
    098
  • wasm调试 webAssembly介绍大全

    https://segmentfault.com/a/1190000040867861 最近在研究 WebAssembly,也写了几篇全面介绍的文章: 本文是学习 WebAssem…

    技术杂谈 2023年5月31日
    076
  • 10个开源WEB后台管理系统

    vue-Element-Admin vue-element-admin 是一个后台前端解决方案,它基于 vue 和 element-ui实现。它使用了最新的前端技术栈,内置了 i1…

    技术杂谈 2023年5月30日
    075
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球