一、前言

本章是redis事务系列知识第一章,redis事务系列主要讲解以下内容:

  1. redis 事务

  2. redis乐观锁讲解

  3. redis乐观锁实现秒杀

我们一步一步来,本章主要讲解事务。

二、事务

2.1事务阐述

讲redis事务之前,我们先来看看事务的定义。

事务:一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。

但redis的事务不并不是完整意义上的事务,我们称之为弱事务,为什么这么说呢?

redis中并没有回滚这种机制,也就是说,在一个事务中,中间一条命令执行失败,并不会导致前面已经执行的指令回滚。也不会造成后续的指令不做。我会在下面画图验证不支持回滚。

2.2 事务命令讲解

事务的命令一共就五条,为了方便大家记忆,我们先记住下面三条命令,:

1.开启事务:MULTI

2.执行事务:EXEC

3.取消事务:DISCARD

就像mysql中用begin开启事务、用commit结束事务一样。redis中是用multi开启事务,用exec执行命令。如果在exec之前你不想执行事务了,可以用discard取消当前事务。下面我们举例说明:

开启事务和执行事务的例子

> multi    //开启事务> set s1 aaa > set s2 bbb> exec    //执行事务> get s1  // 获取s1的值"aaa"> get s2  // 获取s2的值"bbb"

开启事务和取消事务的例子

> multi   //开启事务> set s3 222  > discard //结束事务OK> exec    //因为事务已经在上面取消了,所以在这里执行事务会报错。(error) ERR EXEC without MULTI> get s3  //事务被取消了,所以这里s3根本就没有值(nil)

2.3 事务为什么不支持回滚

讲解“事务为什么不支持回滚”之前我们先来汇总一下redis事务执行异常的几种情况,然后再总结事务为什么不支持回滚。

  1. 语法错误导致事务执行异常,该事务取消

在开启事务后,修改h1值为11111,h2值为2222,但h2语法错误,最终导致事务提交失败,h1、h2保留原值。

> set h1 11> set h2 22> multi      //开启事务> set h1 11111> sets h2 2222   // 语法错误,下面报错(error) ERR unknown command `sets`, with args beginning with: `h2`, `2222`,127.0.0.1:6379> exec   //执行事务,因为前面有语法错误,所以此事务取消(error) EXECABORT Transaction discarded because of previous errors.> get h1  // h1和h2的值并没有在事务中改变"11"> get h2"22"

2.运行时错误(Redis类型错误)导致事务异常

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

> set s1 11> set s2 22> multi> set s1 1111111> lpush s2 2222222 //此处类型错误,s2的类型是字符传,但我们把S2的类型作为List提交> exec  //提交执行事务报错。1) OK2) (error) WRONGTYPE Operation against a key holding the wrong kind of value> get s1  //s1的值修改成功"1111111"> get s2   //s1的值修改失败"22"

总结:为什么Redis不支持事务回滚?

以上两个例子总结出,多数事务失败是由语法错误或者数据结构类型错误导致的,语法错误说明在命令入队前就进行检测的,而类型错误是在执行时检测的,Redis为提升性能而采用这种简单的事务,这是不同于关系型数据库的,特别要注意区分。

2.4 watch和unwatch命令讲解

2.4.1 watch命令

上面我们讲到redis是的事务是不支持回滚的,但是我们一定要让它回滚怎么办呢?这就需要用的watch命令了。

watch使用要注意:watch在mutil命令之前使用.

watch的作用是:监控一个值是否发生变化,如果没发生改变,它会执行事务队列中的命令,提交事务;如果发生变化,将不会执行事务中的任何命令,同时事务回滚。最后无论是否回滚,Redis都会取消执行事务前的WATCH命令。

这么说不太好理解,我们画图表示一下:

下面我们用代码验证一下,场景如下:

在事务开始前用WATCH监控a1,之后修改a1为c1111,MULTI开始事务,修改a2为c2222,执行EXEC,返回nil,说明事务回滚;查看下a2的值都没有被事务中的命令所改变。

代码如下:

//先设置2个值,我们用监控a1,然后用a2判断是否发生的回滚。127.0.0.1:6379> set a1 1111127.0.0.1:6379> set a2 2222127.0.0.1:6379> watch a1 //监听a1127.0.0.1:6379> set a1 c1111 // a1的值在监控后发生了改变。127.0.0.1:6379> multi //开始事务127.0.0.1:6379> set a2 c2222  //设置a2的值127.0.0.1:6379> exec  //执行事务,发生错误,事务回滚(nil)127.0.0.1:6379> get a2 //a2的值并没有被更改,依旧是2222"2222"

2.4.2 unwatch命令

unwatch命令是取消监控,这里就不过多介绍了,下面是代码:

> set k1 1111> set k2 2222> WATCH k1> set k1 11 //改变k1的值> UNWATCH //取消监控> MULTI    //开启事务> set k1 12> set k2 22> exec    //执行事务成功了1) OK2) OK> get k1"12"> get k2"22"

三、结尾

好了,就讲到这里吧,这一章虽然知识点不多,但是小编为了更加通俗地讲出来也想了2、3天。
码字不易,希望大家关注一下小编,感谢!

有什么问题或者意见,大家可以提出来。

大家帮忙关注一下我微信公众号。关注后我有上百套学习资料和视频课程赠送。

事务例子_Redis事务系列之一Redis事务详解相关推荐

  1. python操作redis set_Python操作redis学习系列之(集合)set,redis set详解 (六)

    #-*- coding: utf-8 -*- importredis r= redis.Redis(host="126.56.74.190",port=639,password=& ...

  2. Redis命令详解:Hashs

    Hash是一种String类型的field.value的映射表,因此,它非常适合存储对象.下面我们来一一介绍与Hash相关的命令. HDEL 最早可用版本:2.0.0 时间复杂度:O(N),其中N为要 ...

  3. redis 数据类型详解 以及 redis适用场景场合

    redis 数据类型详解 以及 redis适用场景场合 1. MySql+Memcached架构的问题 实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访 ...

  4. Redis主从复制详解(入门教程)

    文章目录 概念 环境配置 一主二从 配置 测试 复制原理 哨兵模式 概述 测试 哨兵模式全部配置 以下是Redis相关笔记总结,方便自己以后复习,同时也希望对大家有所帮助. 内容 地址链接 Redis ...

  5. Spring和Redis整合详解

    Spring和Redis整合详解 官方主页 Spring Spring Redis 概述 Redis是一个开源(BSD许可)的内存数据结构存储,用作数据库,缓存和消息代理. 简单来说,它是一个以(ke ...

  6. redis数据结构详解之Hash(四)

    原文:redis数据结构详解之Hash(四) 序言 Hash数据结构累似c#中的dictionary,大家对数组应该比较了解,数组是通过索引快速定位到指定元素的,无论是访问数组的第一个元素还是最后一个 ...

  7. RxJS 系列之二 - Observable 详解

    查看新版教程,请访问前端修仙之路 RxJS 系列目录 RxJS 系列之一 - Functional Programming 简介 RxJS 系列之二 - Observable 详解 (本文) RxJS ...

  8. Redis数据结构详解之Zset(五)

    原文:Redis数据结构详解之Zset(五) 序言 Zset跟Set之间可以有并集运算,因为他们存储的数据字符串集合,不能有一样的成员出现在一个zset中,但是为什么有了set还要有zset呢?zse ...

  9. Redis命令详解:Connection

    最近在学习Redis的相关知识,上一篇我们也介绍了Redis的安装方法和基本数据结构,后面就打算开一个新的系列文章:Redis命令详解.既是对基础的巩固,也是为了以后查询起来更方便. 整个系列会分为以 ...

  10. 并发编程系列之volatile关键字详解

    并发编程系列之volatile关键字详解 1.volatile是什么? 首先简单说一下,volatile是什么?volatile是Java中的一个关键字,也是一种同步机制.volatile为了保证变量 ...

最新文章

  1. 1001 A+B Format
  2. 复现经典:《统计学习方法》​第 11 章 条件随机场
  3. 前端学习(1750):前端调试值之call stack
  4. table固定表头滚动
  5. LLE(局部线性嵌入)matlab代码实现
  6. 【LeetCode】剑指 Offer 06. 从尾到头打印链表
  7. Android 获取联系人的公司,android-如何从设备的联系人列表中获取用户...
  8. 为什么 CSS 这么难学?
  9. this.$router.push相关的vue-router的导航方法
  10. mysql repair 索引_MySQ索引操作命令总结(创建、重建、查询和删除索引命令详解)...
  11. python之collections模块Counter类使用学习
  12. BZOj 4540: [Hnoi2016]序列 [莫队 st表 预处理]
  13. Emmet的高级功能与使用技巧
  14. Notebook左侧开启导航
  15. 4.0版本的wed.xml。 中间的部分是配置springMVC的。
  16. GitHub 标星 2.9w+,我发现了一个宝藏项目,作为编程新手有福了!
  17. GXOI/GZOI2019题解
  18. 2021-05-02 收心继续
  19. 简单个人静态HTML网页设计作品 基于HTML+CSS+JavaScript仿小米手机网站 html静态在线购物商城网页制作
  20. java线上培训机构排名前十,重要概念一网打尽!

热门文章

  1. boost::statechart::in_state_reaction相关的测试程序
  2. boost::range模块reversed相关的测试程序
  3. boost::mp11::mp_assign相关用法的测试程序
  4. boost::intrusive::set用法的测试程序
  5. boost::fusion::pair用法的测试程序
  6. boost::function_types::has_property_tag用法的测试程序
  7. GDCM:gdcm::ModuleEntry的测试程序
  8. ITK:计算曲率各向异性扩散
  9. VTK:PolyData之RemoveVertices
  10. VTK:绘图之HistogramBarChart