当前位置: 首页 > news >正文

第八章Redis_ 事务_ 锁机制_ 秒杀

第八章Redis_ 事务_ 锁机制_ 秒杀

文章目录

  • 第八章Redis_ 事务_ 锁机制_ 秒杀
    • 8.1事物的定义
    • 8.2Multi、Exec、discard
    • 8.3为什么要做成事务
    • 8.4事物冲突的例子
      • 8.4.1悲观锁
      • 8.4.2乐观锁
      • 8.4.3乐观锁在redis中的使用
      • 8.4.4unwatch
    • 8.5Redis事务三特性
    • 8.6Redis_ 事务_秒杀案例
      • 8.6.1解决计数器和人员记录的事务操作
      • 8.6.2 Redis 事务--秒杀并发模拟

8.1事物的定义

Redis 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事
务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

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

8.2Multi、Exec、discard

从输入 Multi 命令开始,输入的命令都会依次进入命令队列中,但不会执行,直到输入
Exec后,Redis会将之前的命令队列中的命令依次执行。

组队的过程中可以通过 discard 来放弃组队。
在这里插入图片描述案例
在这里插入图片描述在这里插入图片描述在这里插入图片描述

如果执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚。
在这里插入图片描述

8.3为什么要做成事务

想想一个场景:有很多人有你的账户,同时去参加双十一抢购

8.4事物冲突的例子

一个请求想给金额减 8000
一个请求想给金额减 5000
一个请求想给金额减 1000
在这里插入图片描述

8.4.1悲观锁

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会 block直到它拿到锁。

传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
在这里插入图片描述
想拿10000元会先被上锁,只能被一个操作执行,假设第一个操作需要取8000元,最后面还剩2000元,200

8.4.2乐观锁

在这里插入图片描述

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

8.4.3乐观锁在redis中的使用

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

8.4.4unwatch

取消 WATCH 命令对所有 key 的监视。
如果在执行 WATCH 命令之后,EXEC 命令或 DISCARD 命令先被执行了的话,那么就不需要再执行 UNWATCH 了。
http://doc.redisfans.com/transaction/exec.html

8.5Redis事务三特性

➢ 单独的隔离操作
◼ 事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
➢ 没有隔离级别的概念
◼ 队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行
➢ 不保证原子性
◼ 事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚

8.6Redis_ 事务_秒杀案例

8.6.1解决计数器和人员记录的事务操作

在这里插入图片描述

public static boolean doSecKill(String uid,String prodid) throws IOException {
		//1 uid和prodid非空判断
		if(uid == null || prodid == null) {
			return false;
		}

		//2 连接redis
		//Jedis jedis = new Jedis("192.168.44.168",6379);
		//通过连接池得到jedis对象
		JedisPool jedisPoolInstance = JedisPoolUtil.getJedisPoolInstance();
		Jedis jedis = jedisPoolInstance.getResource();

		//3 拼接key
		// 3.1 库存key
		String kcKey = "sk:"+prodid+":qt";
		// 3.2 秒杀成功用户key
		String userKey = "sk:"+prodid+":user";

		//监视库存
		jedis.watch(kcKey);

		//4 获取库存,如果库存null,秒杀还没有开始
		String kc = jedis.get(kcKey);
		if(kc == null) {
			System.out.println("秒杀还没有开始,请等待");
			jedis.close();
			return false;
		}

		// 5 判断用户是否重复秒杀操作
		if(jedis.sismember(userKey, uid)) {
			System.out.println("已经秒杀成功了,不能重复秒杀");
			jedis.close();
			return false;
		}

		//6 判断如果商品数量,库存数量小于1,秒杀结束
		if(Integer.parseInt(kc)<=0) {
			System.out.println("秒杀已经结束了");
			jedis.close();
			return false;
		}

		//7 秒杀过程
		//使用事务
		Transaction multi = jedis.multi();

		//组队操作
		multi.decr(kcKey);
		multi.sadd(userKey,uid);

		//执行
		List<Object> results = multi.exec();

		if(results == null || results.size()==0) {
			System.out.println("秒杀失败了....");
			jedis.close();
			return false;
		}

		//7.1 库存-1
		//jedis.decr(kcKey);
		//7.2 把秒杀成功用户添加清单里面
		//jedis.sadd(userKey,uid);

		System.out.println("秒杀成功了..");
		jedis.close();
		return true;
	}

在这里插入图片描述

8.6.2 Redis 事务–秒杀并发模拟

使用工具 ab 模拟测试
CentOS6 默认安装
CentOS7 需要手动安装
联网: yum install httpd-tools
在这里插入图片描述
测试及结果
vim postfile 模拟表单提交参数,以&符号结尾;存放当前目录。
内容:prodid=0101&ab -n 2000 -c 200 -k -p ~/postfile -T application/xwww-form-urlencodedhttp://192.168.2.115:8081/Seckill/doseckill
超卖
在这里插入图片描述超卖问题
在这里插入图片描述利用乐观锁淘汰用户,解决超卖问题。
在这里插入图片描述在这里插入图片描述在这里插入图片描述

继续增加并发测试

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述已经秒光,可是还有库存
在这里插入图片描述
在这里插入图片描述连接超时,通过连接池解决
节省每次连接 redis 服务带来的消耗,把连接好的实例反复利用。
通过参数管理连接的行为代码见项目中
链接池参数
◼ MaxTotal:控制一个 pool 可分配多少个 jedis实例,通过 pool.getResource()来获取;如果赋值为-1,则表示不限制;如果 pool已经分配了 MaxTotal 个 jedis实例,则此时 pool 的状态为 exhausted。
◼ maxIdle:控制一个 pool最多有多少个状态为 idle(空闲)的 jedis实例;
◼ MaxWaitMillis :表示当 borrow 一个 jedis 实例时,最大的等待毫秒数,如果超过等待时间,则直 接抛 JedisConnectionException;
◼ testOnBorrow:获得一个 jedis实例的时候是否检查连接可用性(ping());如
果为 true,则得到的 jedis实例均是可用的;
解决库存遗留问题
LUA 脚本
在这里插入图片描述LUA 在 脚本在 Redis 中的优势
在这里插入图片描述
在这里插入图片描述

相关文章:

  • 跨库查询问题
  • [SpringBoot笔记] SpringBoot-01-快速入门案例
  • Java资深架构师带你深度“吃透”字节跳动的亿级流量+高并发,这还不冲?
  • Vue项目实战之电商后台管理系统(八) 订单管理及数据统计模块
  • DAO 的全景图:金融和社会资本之间的关系
  • 《大数据之路:阿里巴巴大数据实践》-第2篇 数据模型篇 -第8章 大数据领域建模综述
  • 上传航测影像就能土方计算?!0基础倾斜摄影土方计算流程
  • C和指针——struct结构
  • 怎么转换音频格式?建议收藏这几个方法
  • 小红书如何养号?小红书如何精准引流?
  • 音频裁剪软件有哪些?来看看这几个实用软件
  • 极智开发 | linux 下 ssh 或 scp 免密连接配置方法
  • 离线数仓搭建_02_服务器配置与数据生产
  • 猿创征文|我的四个月Java学习成长之路——从基础到框架再到项目
  • 【毕业设计】试卷自动批改系统 - opencv python 机器视觉
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • angular组件开发
  • Hibernate【inverse和cascade属性】知识要点
  • java正则表式的使用
  • mockjs让前端开发独立于后端
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • Python_网络编程
  • 大数据与云计算学习:数据分析(二)
  • - 概述 - 《设计模式(极简c++版)》
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 山寨一个 Promise
  • 推荐一个React的管理后台框架
  • #Linux(帮助手册)
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (1)(1.11) SiK Radio v2(一)
  • (1)bark-ml
  • (2)STL算法之元素计数
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (附源码)ssm本科教学合格评估管理系统 毕业设计 180916
  • (南京观海微电子)——COF介绍
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (转)可以带来幸福的一本书
  • . Flume面试题
  • .NET 依赖注入和配置系统
  • @Data注解的作用
  • @font-face 用字体画图标
  • [ 渗透测试面试篇 ] 渗透测试面试题大集合(详解)(十)RCE (远程代码/命令执行漏洞)相关面试题
  • [BZOJ 4598][Sdoi2016]模式字符串
  • [BZOJ]4817: [Sdoi2017]树点涂色
  • [C/C++]数据结构 栈和队列()
  • [CF]Codeforces Round #551 (Div. 2)
  • [hdu4622 Reincarnation]后缀数组
  • [IE编程] 多页面基于IE内核浏览器的代码示例
  • [Linux] - 定时任务crontab