带你详细了解Redis事务锁机制-加实列演示-上

news2024/11/24 17:42:48

Redis_事务_锁机制_秒杀

Redis 的事务是什么?

1、Redis 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行

2、事务在执行的过程中,不会被其他客户端发送来的命令请求所打断

3、Redis 事务的主要作用就是串联多个命令防止别的命令插队

Redis 事务三特性

一单独的隔离操作

1、事务中的所有命令都会序列化、按顺序地执行

2、事务在执行的过程中,不会被其他客户端发送来的命令请求所打断

二没有隔离级别的概念

队列中的命令(指令), 在没有提交前都不会实际被执行

三不保证原子性

事务执行过程中, 如果有指令执行失败,其它的指令仍然会被执行, 没有回滚

事务相关指令Multi、Exec、discard

示意图

Redis 事务指令示意图

在这里插入图片描述

解读上图
  1. 从输入Multi 命令开始,输入的命令都会依次进入命令队列中,但不会执行(类似Mysql的start transaction 开启事务)
  2. 输入Exec 后,Redis 会将之前的命令队列中的命令依次执行(类似Mysql 的commit 提交事务)
  3. 组队的过程中可以通过discard 来放弃组队(类似Mysql 的rollback 回顾事务)
  4. 说明: Redis 事务和Mysql 事务本质是完全不同的, 用Mysql 的做类似说明, 是为了好理解

快速入门

1、需求: 请依次向Redis 中, 添加三组数据, k1-v1 k2-v2 k3-v3, 要求使用Redis 的事务完成

在这里插入图片描述

注意事项和细节

1、组队的过程中, 可以通过discard 来放弃组队

在这里插入图片描述

2、如果在组队阶段报错, 会导致exec 失败, 那么事务的所有指令都不会被执行
在这里插入图片描述

在这里插入图片描述

3、如果组队成功, 但是指令有不能正常执行的, 那么exec 提交, 会出现有成功有失败情况,也就是事务得到部分执行, 这种情况下, Redis 事务不具备原子性.

在这里插入图片描述

在这里插入图片描述

事务冲突及解决方案

先看一个问题

经典的抢票问题

  1. 一个请求想购买6

  2. 一个请求想购买5

  3. 一个请求想购买1
    在这里插入图片描述

解读上图

  1. 如果没有控制, 会造成超卖现象
  2. 如果3 个指令, 都得到执行, 最后剩余的票数是-2

悲观锁

工作示意图

在这里插入图片描述

解读上图

  1. 悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁
  2. 这样别人/其它请求想拿这个数据就会block 直到它拿到锁。
  3. 悲观锁是锁设计理念, 传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁.

乐观锁

工作示意图

在这里插入图片描述

解读上图

  1. 乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁
  2. 但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。
  3. 乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis 就是利用这种check-and-set机制实现事务的
  4. 乐观锁是锁设计理念

watch & unwatch

watch

1、基本语法: watch key [key …]

2、在执行multi 之前,先执行watch key1 [key2],可以监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断.

3、这里可以结合乐观锁机制进行理解.

实验:

在这里插入图片描述

unwatch

1、基本语法unwatch

2、取消watch 命令对所有key 的监视。

3、如果在执行watch 命令后,exec 命令或discard 命令先被执行了的话,那么就不需要再执行unwatch 了

火车票-抢票

需求分析/图解

创建一个web项目

在这里插入图片描述

思路分析

1、一个user 只能购买一张票, 即不能复购

2、不能出现超购,也是就多卖了.

3、不能出现火车票遗留问题/库存遗留, 即火车票不能留下

在这里插入图片描述

版本1:完成基本购票流程, 暂不考虑事务和并发问题

1、创建Java Web 项目, 参照以前讲过搭建Java Web 项目流程即可

2、引入相关的jar 包和jquery

创建index

sec_kill_ticket\web\index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>Insert title here</title>
  <base href="<%=request.getContextPath() + "/"%>">
</head>
<body>
<h1>北京-成都 火车票 ! 秒杀!
</h1>


<form id="secKillform" action="secKillServlet" enctype="application/x-www-form-urlencoded">
  <input type="hidden" id="ticketNo" name="ticketNo" value="bj_cd">
  <input type="button" id="seckillBtn" name="seckillBtn" value="秒杀火车票【北京-成都】"/>
</form>

</body>
<script type="text/javascript" src="script/jquery/jquery-3.1.0.js"></script>
<script type="text/javascript">
  $(function () {
    $("#seckillBtn").click(function () {
      var url = $("#secKillform").attr("action");
      console.log("url->" , url)// secKillServlet,完整的url http://localhost:8080/seckill/secKillServlet
      console.log("serialize->", $("#secKillform").serialize())
      //
      $.post(url, $("#secKillform").serialize(), function (data) {
        if (data == "false") {
          alert("火车票 抢光了:)");
          $("#seckillBtn").attr("disabled", true);
        }
      });
    })
  })
</script>
</html>

创建SecKillRedis

src\com\seckill\redis\SecKillRedis.java

public class SecKillRedis {
    /**
     * 测试一下是否连通了Redis
     *
     * @param args
     */
    public static void main(String[] args) {
        Jedis jedis = new Jedis("192.168.198.130", 6379);
        System.out.println(jedis.ping());
        jedis.close();
    }
    //秒杀过程
    /**
     * @param uid 用户id
     * @param ticketNo 票编号, 比如北京-成都的ticketNo "bj_cd"
     * @return
     */
    public static boolean doSecKill(String uid, String ticketNo) {
        //1 uid 和ticketNo 非空判断
        if (uid == null || ticketNo == null) {
            return false;
        }
        //2.连接到redis
        //解读
        //1) 每一个来秒杀的用户, 都会连接一把Reids
        Jedis jedis = new Jedis("192.168.198.130", 6379);
        //3 拼接key
        // 3.1 库存key
        String stockKey = "sk:" + ticketNo + ":ticket";
        // 3.2 秒杀成功用户key=> 对应的值是set , 可以存放有多个秒杀成功用户的id
        String userKey = "sk:" + ticketNo + ":user";
        //4 获取库存,如果库存null,秒杀还没有开始
        String stock = jedis.get(stockKey);
        if (stock == null) {
            System.out.println("秒杀还没有开始,请等待..");
            jedis.close();
            return false;
        }
        // 5 判断用户是否重复秒杀操作
        if (jedis.sismember(userKey, uid)) {
            System.out.println(uid + " 不能重复秒杀...");
            jedis.close();
            return false;
        }
        //6 判断如果火车票数量,剩余数量小于1,秒杀结束
        if (Integer.parseInt(stock) <= 0) {
            System.out.println("票已经卖光, 秒杀已经结束了");
            jedis.close();
            return false;
        }
        //7.1 火车票数量- 1
        jedis.decr(stockKey);
        //7.2 把秒杀成功用户添加清单里面
        jedis.sadd(userKey, uid);
        System.out.println("秒杀成功了..");
        jedis.close();
        return true;
    }
}

创建SecKillServlet

src\com\seckill\web\SecKillServlet.java

public class SecKillServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //请求时, 模拟生成一个userId
        String userId = new Random().nextInt(10000) + "";
        //获取用户要购买的票的编号
        String ticketNo = request.getParameter("ticketNo");
        //调用秒杀
        boolean isOK = SecKillRedis.doSecKill(userId, ticketNo);
        //返回结果
        response.getWriter().print(isOK);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
            ServletException, IOException {
        doPost(request, response);
    }
}

向Redis 中, 增加测试数据

在这里插入图片描述

测试效果

在这里插入图片描述

版本2:抢票并发模拟, 出现超卖问题

安装工具ab 模拟测试

  1. 说明: 工具ab 可以模拟并发发出Http 请求, 老韩说明(模拟并发http 请求工具还有jemeter, postman,我们都使用一下, 开阔眼界, 这里老师使用ab 工具)
  2. 安装指令: yum install httpd-tools (提示: 保证当前linux 是可以联网的)
  3. 如果你不能联网, 可以使用rpm 安装, 这里使用yum 方式安装
  4. 另外, 使用rpm 方式安装我也给小伙伴说明一下, 如下:-先挂载centos 安装文件ios, 这个文件

在这里插入图片描述

在这里插入图片描述

–进入cd /run/media/root/CentOS 7 x86_64/Packages

–顺序安装

  1. apr-1.4.8-3.el7.x86_64.rpm
  2. apr-util-1.5.2-6.el7.x86_64.rpm
  3. httpd-tools-2.4.6-67.el7.centos.x86_64.rpm
    在这里插入图片描述

–测试是否安装成功

在这里插入图片描述

在ab 指令执行的当前路径下创建文件postfile

vi postfile

在这里插入图片描述

在这里插入图片描述

执行指令

注意保证linux 可以访问到Tomcat 所在的服务器.

–先查看Tomcat 所在Windows 的网络配置情况
在这里插入图片描述

–确认Linux 可以ping 通Windows

在这里插入图片描述

如果Ping 不通, 确认一下Windows 防火墙是否关闭
在这里插入图片描述

--指令, 测试前把Redis 的数据先重置一下
ab -n 1000 -c 100 -p ~/postfile -T application/x-www-form-urlencoded http://192.168.198.1:8080/seckill/secKillServlet

解读指令

(1) ab 是并发工具程序

(2) -n 1000 表示一共发出1000 次http 请求

(3) -c 100 表示并发时100 次, 你可以理解1000 次请求, 会在10 次发送完毕

(4) -p ~/postfile 表示发送请求时, 携带的参数从当前目录的postfile 文件读取(这个你事先要准备好)

(5) -T application/x-www-form-urlencoded 就是发送数据的编码是基于表单的url 编码

(6) ~的含义: https://blog.csdn.net/m0_67401134/article/details/123973115

在这里插入图片描述

(7)http://192.168.198.1:8080/seckill/secKillServlet 就是请求的url, 注意这里的IP:port/uri 必须写正确.

在这里插入图片描述
在这里插入图片描述

查看执行结果

在这里插入图片描述
在这里插入图片描述

注意我们这里先讲连接池然后在讲解决方法

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

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

相关文章

怎么学习和提升前端开发的能力? - 易智编译EaseEditing

要学习和提升前端开发的能力&#xff0c;您可以按照以下步骤进行&#xff1a; 掌握基础知识&#xff1a; 了解HTML、CSS和JavaScript的基本概念和语法。学习HTML用于创建网页结构&#xff0c;CSS用于样式设计和布局&#xff0c;JavaScript用于交互和动态效果。 学习框架和库&…

探讨太阳能热水器的安全隐患和雷电防护措施

太阳能热水器是指利用太阳光加热原理来获得热水的装置。随着科学技术的发展&#xff0c;太阳能热水器因其新颖、环保、节能且方便而深受消费者的喜爱&#xff0c;安装数量逐年增加。我国太阳能资源丰富&#xff0c;尤其是在广袤的西部中小城镇、农村地区&#xff0c;家家户户几…

NSSA实验和配置命令

1)拓扑 需求 2)需求&#xff1a;PC2和PC5互通 配置思路和配置命令 3&#xff09;配置思路&#xff1a; 第一步&#xff1a;先让R1能够和PC5互通&#xff0c;要先配置静态路由 [R1] ip route-static 192.168.4.0 24 192.168.18.8 第二步&#xff1a;在R8上写去往PC1/PC2的路…

定长图文验证码模型训练

文章目录 自定义数据集生成模型代码计算均值和标准差训练代码测试集成功率计算推理测试 市面上常见的验证码识别方案包括&#xff1a; 基于规则的方案&#xff1a;这种识别方案针对一些特定类型的验证码&#xff08;如数字、字母组合&#xff09;&#xff0c;利用编写规则的方式…

逛开发者集市啦,ShardingSphere 在亚马逊云科技中国峰会等你!

2023亚马逊云科技中国峰会将于6月27日-28日在上海世博中心盛大开幕。本次峰会以“共见价值成就”为主题&#xff0c;与合作伙伴展望云计算趋势及合作发展战略&#xff0c;分享行业解决方案&#xff0c;共同探讨协同销售策略和全新的 APN 计划&#xff0c;助力合作伙伴成就更多价…

计算机系统层次结构与操作系统和驱动的定义

一、程序分类 程序按其运行环境分为&#xff1a; 裸机程序&#xff1a;直接运行在对应硬件上的程序 应用程序&#xff1a;只能运行在对应操作系统上的程序 二、计算机系统的层次结构 计算机系统两种层次结构&#xff1a; 2.1 无操作系统的简单的两层结构 2.2 有操作系统的…

华为云物联网平台微信小程序开发教程2.0【完整详细教程】

一、简介 在之前曾发布过一篇文章“华为云物联网平台的微信小程序开发”&#xff0c;在最近接到部分用户私信在使用开发过程中出现的问题&#xff0c;例如API访问的"401"现象等问题&#xff0c;在重新查看上面的文章教程时发现教程内容的步骤不详细&#xff0c;现对教…

Postman快速入门(一)

一、基本介绍 postman是一款流程的接口调试工具&#xff0c;其特点就是使用简单&#xff0c;功能强大。使用角色也非常广泛&#xff0c;后端开发&#xff0c;前端人员&#xff0c;测试人员都可以使用它进行接口调试或测试。 下图是基本功能介绍 发送第一个请求 如果你是第一次…

人工智能如何彻底改变 SaaS 格局

人工智能 (AI) 正在颠覆几乎所有行业&#xff0c;并正在改变我们开展业务的方式。近年来&#xff0c;SaaS 行业一直是受影响最大的行业之一&#xff0c;人工智能在其指数级增长中发挥着至关重要的作用。在本文中&#xff0c;我们将详细讨论实施 AI 对 SaaS 产品的增长和开发有何…

C++拷贝构造函数

文章目录 拷贝构造函数是一个c的默认成员函数&#xff0c;它是用来拷贝对象的&#xff0c;当你想修改对象&#xff0c;但是又不想修改它本身&#xff0c;那么可以将其拷贝给一个对象对这个拷贝出来的对象进行操作 拷贝构造函数语法&#xff1a;类名&#xff08;const 类名&…

Java-API简析_java.util.StringTokenizer类(基于 Latest JDK)(浅析源码)

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/131293596 出自【进步*于辰的博客】 其实我的【Java-API】专栏内的博文对大家来说意义是不大的。…

设计模式之——单例模式

✍&#x1f3fc;作者&#xff1a;周棋洛&#xff0c;计算机学生 ♉星座&#xff1a;金牛座 &#x1f3e0;主页&#xff1a;点击学习更多 &#x1f310;关键&#xff1a;JavaScript 单例 设计模式 单例模式的定义是&#xff1a;保证一个类仅有一个实例&#xff0c;并提供一个访问…

【操作系统】程序运行环境

目录 1.处理器运行模式 1.1特权指令 1.2非特权指令 2.中断和异常的概念 2.1中断和异常的定义 2.1.1外中断 2.1.2内中断&#xff08;异常&#xff09; 2.2中断和异常的处理过程 3.系统调用 1.处理器运行模式 计算机系统中&#xff0c;通常 CPU 执行两种不同性质的程序:一…

【Android开发基础】手机传感器信息的获取

文章目录 一、引言二、了解1、概述2、关键 三、设计1、UI设计&#xff08;1&#xff09;主界面&#xff08;2&#xff09;适配器item 2、编码&#xff08;1&#xff09;获取数据&#xff08;传感器信息&#xff09;&#xff08;2&#xff09;渲染数据&#xff08;初始化适配器&…

SpringBoot不在使用@Validated 做参数校验但是不想在Controller层怎么办?

目录 场景再现&#xff1a; 怎么做&#xff1f; 遇到了什么问题&#xff1f; 怎么实现&#xff1f; 场景再现&#xff1a; 某API接口接受加密的json字符串&#xff0c;接受字符串之后先进行解密处理&#xff0c;解密完成之后还要进行参数校验处理&#xff0c;如果参数不合规…

华为HCIA备考(数通) 易错题整理 PART1

1.IEEE802.1Q定义的 VLAN 帧格式中VLAN ID总共有多少bit 答&#xff1a;12 2.NAPT允许多个私有IP地址通过不同的端口号映射到同一个公有IP地址上&#xff0c;且不需要做任何关于端口号的配置。 3.IEEE802.1Q定义的VLAN帧总长度为多少字节&#xff1f; 答&#xff1a;4 4.关于…

2023亚马逊云科技中国峰会:强化学习探索—— Amazon DeepRacer

1️⃣前言 Amazon DeepRacer 是一个综合性的学习系统&#xff0c;可供各个水平的用户用来学习和探索强化学习以及试验和构建自动驾驶应用程序。 2️⃣Amazon DeepRacer 介绍 DeepRacer是一款小型自主驾驶车辆&#xff0c;它结合了深度学习、强化学习和云计算等技术&#xff0c…

Karl Guttag评Vision Pro(二):这些硬件问题不容忽视

上周&#xff0c;AR/VR光学专家Karl Guttag从价格、VST透视、应用、交互等方面&#xff0c;将Vision Pro与Quest Pro进行对比&#xff0c;发现Vision Pro在设计上做出更多正确决策。尽管如此&#xff0c;Guttag认为该头显本身在硬件部分&#xff0c;依然存在一些不易发现的问题…

C语言结构体计算大小结构体的对齐数,修改默认对齐数。

结构体的对齐规则 第一个成员在与结构体变量偏移量为0的地址处。剩余成员变量要对齐到对齐数的整数倍的地址处。 对齐数&#xff1a;编译器默认对齐数与该成员大小的较小值vs中默认对齐数为8没有默认对齐数&#xff0c;那么对齐数就是其本身成员大小 结构体总大小为最大对齐数…

2个小工具让你轻松解决大数据/数据库测试

目录 前言&#xff1a; 研究背景 工具 支持功能 支持功能 使用方法 总结 前言&#xff1a; 做大数据/数据库测试时&#xff0c;通常需要编写复杂的测试用例代码或手动操作来测试系统的正确性和稳定性。但是&#xff0c;有些小工具可以轻松解决这个问题&#xff0c;提高测试效率…