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

Redis事务+秒杀案例

        Redis事务是一个单独的隔离操作,是指将多条命令放在一个命令队列当中,按顺序执行,保证多个命令在同一个事务中执行而不受其他客户端的影响。

        通俗来说就是:串联多个命令防止别的命令插队。

1.Multi、Exec、discard

        在输入Multi命令后,输入的命令都会依次进入命令队列中,这一过程也叫组队,直到输入Exec后,Redis会将命令队列中的命令依次执行。如下示例:

        而且在组队的过程中可以通过discard来退出输入,结束这个事务。如下示例:  

 

2.事务错误的处理

2.1组队的过程中报错

        如果组队的过程中添加命令时出现了错误,那么输入exec执行时队列中所有的命令都不会执行。  

2.2执行过程中报错

redis的事务中不会保证原子性,其中第二条命令有误,并不会影响命令1和命令3的执行。

3.Redis怎么解决事务冲突问题(watch)

        比如高并发下多个请求同时操作同一个账户,那么账户余额就可能出现问题,正常情况可以采用悲观锁或者乐观锁来解决。其中悲观锁实现就是给账户余额加锁,同一时间只能由一个事务来操作。乐观锁实现就是通过版本号来控制。但是乐观锁适用于读多写少的场景,而Redis就是利用乐观锁这种CAS机制来解决事务冲突问题的。

3.1对watch我的理解

        有客户端A和B,客户端A执行了watch key,就代表着A监视着此key,A会保存一份key的当前版本号,如果(无论什么地方)修改了此key的值,那么key的版本号就会发生变更。

        而判断比较key的版本号,这个环节只和事务有关系,只会在multi开启事务后,然后exec执行命令时才会生效。比如多个事务在输入multi命令之前,可以先执行watch key1 ....,用来监视一个或多个key,如果事务A在exec执行时发现事务A监视的key的版本已经被改动,那么这个事务A的命令队列就会被打断,命令全部不会执行,当操作被打断时,会返回空值nil

4.Redis事务的三大特性

  • 单独的隔离操作。

  • 没有隔离级别的概念。

  • 不保证原子性,出现错误继续向下执行。

5.秒杀案例

我们通过ab工具实现了并发模拟秒杀,结果出现了库存超卖和redis连接超时的问题。以下分析出现原因:

  • 超卖:在高并发请求下,多个请求同时开始查询到的是有库存的,然后就一窝蜂的去减库存,就会导致超卖。

  • 连接超时:因为redis是单线程操作内存,如果一瞬间请求过多,一直排在后面的请求就可能会产生连接超时。

5.1解决超卖问题

如果只需解决超卖问题其实也不难,我们可以使用watch来监视库存,从而使用乐观锁解决超卖的问题。

示例代码(qtkey表示的是库存的键,userkey表示存放用户id的key):

//增加乐观锁,监视库存
jedis.watch(qtkey);
//判断库存
String qtkeystr = jedis.get(qtkey);
if(qtkeystr==null || "".equals(qtkeystr.trim())) {System.out.println("未初始化库存");jedis.close();return false ;
}
int qt = Integer.parseInt(qtkeystr);
if(qt<=0) {System.err.println("已经秒光");jedis.close();return false;
}
//增加事务
Transaction multi = jedis.multi();
//减少库存
multi.decr(qtkey);
//添加用户信息
multi.sadd(usrkey, uid);
//执行事务
List<Object> list = multi.exec();
//判断事务提交是否失败
if(list==null || list.size()==0) {System.out.println("秒杀失败");jedis.close();return false;
}
System.err.println("秒杀成功");
jedis.close();

5.2解决连接超时的问题

        问题就是每个请求都要自己等待去建立和关闭连接,我们使用连接池来解决即可,连接池还能节省每次连接redis服务带来的消耗,能反复利用。

5.3库存遗留怎么解决

        我们使用乐观锁能够很好的解决超卖的问题,但是无法解决库存遗留的问题,比如库存余额为10,此时有50个请求同时过来,但是由于CAS导致很多的请求都失败了,导致先点的没抢到,后来的反而抢到了。虽然请求很多,但最终都可能导致还有库存遗留,这样就不太好。

        而且redis不支持悲观锁,所以用LUA脚本来解决。

        LUA是一个脚本语言,LUA脚本有一定的原子性不会被其他命令插队。我们将多步操作,写为一个脚本,一次性的交给redis执行。

        因为redis其单线程的特性,同一时间只能将一个LUA脚本彻彻底底的执行完后,才能执行下一个LUA脚本,所以LUA能同时解决超卖的问题和库存遗留的问题

相关文章:

Redis事务+秒杀案例

Redis事务是一个单独的隔离操作&#xff0c;是指将多条命令放在一个命令队列当中&#xff0c;按顺序执行&#xff0c;保证多个命令在同一个事务中执行而不受其他客户端的影响。 通俗来说就是&#xff1a;串联多个命令防止别的命令插队。 1.Multi、Exec、discard 在输入Multi命…...

目标分割技术-语义分割总览

前言 博主现任高级人工智能工程师&#xff0c;曾发表多篇SCI且获得过多次国际竞赛奖项&#xff0c;理解各类模型原理以及每种模型的建模流程和各类题目分析方法。目的就是为了让零基础快速使用各类代码模型&#xff0c;每一篇文章都包含实战项目以及可运行代码。欢迎大家订阅一…...

基于C#实现最长公共子序列

一、作用 最长公共子序列的问题常用于解决字符串的相似度&#xff0c;是一个非常实用的算法&#xff0c;作为码农&#xff0c;此算法是我们的必备基本功。 二、概念 举个例子&#xff0c;cnblogs 这个字符串中子序列有多少个呢&#xff1f;很显然有 27 个&#xff0c;比如其…...

物联网AI MicroPython学习之语法 SPI串行外设通信

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; SPI 介绍 模块功能: SPI串行外设驱动 接口说明 SPI - 构建SPI对象 函数原型&#xff1a;SPI(id, baudrate&#xff0c;polarity, phase&#xff0c;sck, mosi, miso)参数说明&#xff1a; 参数类型必选参…...

电动汽车充放电V2G模型MATLAB代码

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 主要内容&#xff1a; 本程序主要建立电动汽车充放电V2G模型&#xff0c;采用粒子群算法&#xff0c;在保证电动汽车用户出行需求的前提下&#xff0c;为了使工作区域电动汽车尽可能多的消纳供给商场基础负荷…...

【大数据Hive】hive 优化策略之job任务优化

目录 一、前言 二、hive执行计划 2.1 hive explain简介 2.1.1 语法格式 2.1.2 查询计划阶段说明 2.2 操作演示 2.2.1 不加条件的查询计划分析 2.2.2 带条件的查询计划分析 三、MapReduce属性优化 3.1 本地模式 3.1.1 本地模式参数设置 3.1.2 本地模式操作演示 3.2 …...

OpenAI再次与Altman谈判;ChatGPT Voice正式上线

11月22日&#xff0c;金融时报消息&#xff0c;OpenAI迫于超过700名员工联名信的压力&#xff0c;再次启动了与Sam Altman的谈判&#xff0c;希望他回归董事会。 在Sam确定加入微软后&#xff0c;OpenAI超700名员工签署了一封联名信&#xff0c;要求Sam和Greg Brockman&#x…...

【JS】Chapter15-高阶技巧

站在巨人的肩膀上 黑马程序员前端JavaScript入门到精通全套视频教程&#xff0c;javascript核心进阶ES6语法、API、js高级等基础知识和实战教程 &#xff08;十五&#xff09;高阶技巧 1. 深浅拷贝 开发中我们经常需要复制一个对象。如果直接用赋值会有下面问题&#xff1a;/…...

Google Chrome 任意文件读取 (CVE-2023-4357)漏洞

漏洞描述 该漏洞的存在是由于 Google Chrome 中用户提供的 XML 输入验证不足。远程攻击者可以创建特制网页&#xff0c;诱骗受害者访问该网页并获取用户系统上的敏感信息。远程攻击者可利用该漏洞通过构建的 HTML 页面绕过文件访问限制&#xff0c;导致chrome任意文件读取。Li…...

psql 模式(SCHEMA)

模式是数据库领域的一个基本概念&#xff0c;有些数据库把模式和用户合二为一了&#xff0c;而postgresql则是有清晰的模式定义。 模式是数据库中的一个概念&#xff0c;可以理解为一个命名空间或目录&#xff0c;不同模式下可以有相同名称的表、函数等对象而不会产生冲突。提出…...

网络吞吐量 公网带宽有关吗?

环境&#xff1a; 华为交换机 深信服防火墙 问题描述&#xff1a; 网络吞吐量 公网带宽有关吗&#xff1f; 解决方案&#xff1a; 网络吞吐量网络吞吐量是指在特定时间内通过网络传输的数据量。它衡量了网络设备&#xff08;如防火墙、交换机、路由器&#xff09;或网络连…...

Linux设置静态IP

Linux设置静态IP 使用ip addr查看ip&#xff0c;如下所示就是动态IP 1、什么是静态IP&#xff1f; 静态ip就是固定的ip&#xff0c;需要手动设置。静态IP地址&#xff08;又称固定IP地址&#xff09;是长期分配给一台计算机或网络设备使用的 IP 地址。一般来说&#xff0c;一…...

六、Big Data Tools安装

1、安装 在Jetbrains的任意一款产品中&#xff0c;均可安装Big Data Tools这个插件。 2、示例 下面以DadaGrip为例&#xff1a; &#xff08;1&#xff09;打开插件中心 &#xff08;2&#xff09;搜索Big Data Tools&#xff0c;下载 3、链接hdfs &#xff08;1&#xff0…...

数据结构【DS】特殊二叉树

完全二叉树 叶子结点只能出现在最下层和次下层, 最下层的叶子结点集中在树的左部完全二叉树中, 度为1的节点数 0个或者1个【计算时可以用这个快速计算, 配合&#x1d45b;0&#x1d45b;21】若n为奇数&#xff0c;则分支节点每个都有左右孩子&#xff1b;若n为偶数&#xff0…...

【Spring Boot】如何在Linux系统中快速启动Spring Boot的jar包

在Linux系统中先安装java的JDK 然后编写下列service.sh脚本&#xff0c;并根据自己的需求只需要修改export的log_path、exec_cmd参数即可 # 配置运行日志输出的路径 export log_path/usr/local/project/study-pro/logs # 当前服务运行的脚本命令 export exec_cmd"nohup /u…...

交替最小二乘法

前置概念导入 协同过滤&#xff08;Collaborative Filtering&#xff09;&#xff1a;这是一种推荐系统的方法&#xff0c;依据用户之间或物品之间的相似性来进行推荐。协同过滤通常分为两种主要类型&#xff1a;用户基于&#xff08;user-based&#xff09;和物品基于&#xf…...

封面从这里取好啦

文章目录 前端NPMViteNode.js 后端JavaMavenPython 数据库算法 前端 NPM Vite Node.js 后端 Java Maven Python 数据库 算法...

DM8共享集群DSC初始化DB实例报错

DM8共享集群DSC初始化DB实例报错 问题描述 启动dmcss和dmasmsvr服务启动后&#xff0c;初始化DB实例提示如下报错&#xff1a; [dmdbalocalhost DSC0]$ /dmdb8/dmdbms/bin/dminit control/dmdb8/dmdbms/dsc_config/DSC0/dminit.ini initdb V8 db version: 0x7000c file dm.k…...

大师学SwiftUI第18章Part1 - 图片选择器和相机

如今&#xff0c;个人设备主要用于处理图片、视频和声音&#xff0c;苹果的设备也不例外。SwiftUI可以通过​​Image​​视图显示图片&#xff0c;但需要其它框架的支持来处理图片、在屏幕上展示视频或是播放声音。本章中我们将展示Apple所提供的这类工具。 图片选择器 Swift…...

【电子通识】USB3.0和USB2.0有什么区别?

版本 USB2.0是2000年4月27日由USB-IF组织提出了USB2.0总线协议规范。 USB3.0是2008年11月17日由USB-IF组织提出了超高速USB3.0规范。 图标对比 USB2.0的标志就是和USB1.1的标志基本上没啥区别&#xff0c;还是以前的那个样子&#xff0c;使用黑色颜色用标识 USB3.0它有一个S…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

MFC 抛体运动模拟:常见问题解决与界面美化

在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

华为OD机考-机房布局

import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...

计算机基础知识解析:从应用到架构的全面拆解

目录 前言 1、 计算机的应用领域&#xff1a;无处不在的数字助手 2、 计算机的进化史&#xff1a;从算盘到量子计算 3、计算机的分类&#xff1a;不止 “台式机和笔记本” 4、计算机的组件&#xff1a;硬件与软件的协同 4.1 硬件&#xff1a;五大核心部件 4.2 软件&#…...