百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Java秒杀系统实战系列-数据库级别Sql的优化与代码的调整

toyiye 2024-07-08 00:34 18 浏览 0 评论


本文是“Java秒杀系统实战系列文章”的第十三篇,从本篇文章开始我们将进入“秒杀代码优化”环节,本文将首先从数据库级别Sql的优化入手,结合调整秒杀相关的部分核心代码,实现初步的优化!

上篇文章《Meter压力测试重现秒杀场景中超卖等问题》我们暴露出了“秒杀接口”在面对高并发请求的场景下所出现的“超卖”、“重复秒杀”等问题,并对相应的问题进行了分析,然后就没有然后了……(事了拂衣去!)

问题既然落在我们的手里,那么身为一名程序猿,那是没有理由回避的。通过分析该“秒杀接口”的核心代码,可以发现在数据库层面,其涉及的Sql我们还是可以动一动手脚的!其调整后的“秒杀核心业务逻辑”的完整源代码如下所示:


//商品秒杀核心业务逻辑的处理-mysql的优化
@Override
public Boolean killItemV2(Integer killId, Integer userId) throws Exception {
 Boolean result=false;
 //TODO:判断当前用户是否已经抢购过当前商品
 if (itemKillSuccessMapper.countByKillUserId(killId,userId) <= 0){
 //A 查询待秒杀商品详情
 ItemKill itemKill=itemKillMapper.selectByIdV2(killId);
 //TODO:判断是否可以被秒杀canKill=1?
 if (itemKill!=null && 1==itemKill.getCanKill() && itemKill.getTotal()>0){
 //B 扣减库存-减一
 int res=itemKillMapper.updateKillItemV2(killId);
 //TODO:扣减是否成功?是-生成秒杀成功的订单,同时通知用户秒杀成功的消息
 if (res>0){
 commonRecordKillSuccessInfo(itemKill,userId);
 result=true;
 }
 }
 }else{
 throw new Exception("您已经抢购过该商品了!");
 }
 return result;
}

△向右滑动查看

首先是对于 注释A 那里的调整,即在获取“秒杀商品详情”时,我们限定了“可秒杀商品的数量total需要大于0”,其对应的代码为:itemKillMapper.updateKillItemV2(killId);完整的动态Sql如下所示:



<!--获取秒杀详情V2-->
<select id="selectByIdV2" resultType="com.debug.kill.model.entity.ItemKill">
 SELECT
 a.*,
 b.name AS itemName,
 (CASE WHEN (now() BETWEEN a.start_time AND a.end_time)
 THEN 1
 ELSE 0
 END) AS canKill
 FROM item_kill AS a LEFT JOIN item AS b ON b.id = a.item_id
 WHERE a.is_active = 1 AND a.id =#{id} AND a.total>0
</select>

△向右滑动查看

然后是 注释B 对应的优化调整,即在扣减库存时,我们除了可以保证正常减1的操作之外,还需要保证扣减完之后的数量大于0,即只有在保证扣减完之后的数量大于0之下,该Sql操作后受影响的行数为1,对应的代码为:itemKillMapper.updateKillItemV2(killId);其对应的动态Sql如下所示:


<!--抢购商品,剩余数量减一-->
<update id="updateKillItemV2">
 UPDATE item_kill
 SET total = total - 1
 WHERE id = #{killId} AND total>0
</update>

至此,我们在秒杀核心业务逻辑的优化层面~数据库级别Sql的优化 已经搞完了!除此之外,我们还在代码层面进行优化,如下所示:


private void commonRecordKillSuccessInfo(ItemKill kill, Integer userId) throws Exception{
 //TODO:记录抢购成功后生成的秒杀订单记录
 ItemKillSuccess entity=new ItemKillSuccess();
 String orderNo=String.valueOf(snowFlake.nextId());
 //entity.setCode(RandomUtil.generateOrderCode()); //传统时间戳+N位随机数
 entity.setCode(orderNo); //雪花算法
 entity.setItemId(kill.getItemId());
 entity.setKillId(kill.getId());
 entity.setUserId(userId.toString());
 entity.setStatus(SysConstant.OrderStatus.SuccessNotPayed.getCode().byteValue());
 entity.setCreateTime(DateTime.now().toDate());
 //TODO:学以致用,举一反三 -> 仿照单例模式的双重检验锁写法
 if (itemKillSuccessMapper.countByKillUserId(kill.getId(),userId) <= 0){
 int res=itemKillSuccessMapper.insertSelective(entity);
 if (res>0){
 //TODO:进行异步邮件消息的通知=rabbitmq+mail
 rabbitSenderService.sendKillSuccessEmailMsg(orderNo);
 //TODO:入死信队列,用于 “失效” 超过指定的TTL时间时仍然未支付的订单
 rabbitSenderService.sendKillSuccessOrderExpireMsg(orderNo);
 }
 }
}

△向右滑动查看


即我们在“用户秒杀成功生成订单记录”的代码加入了类似于“单例模式”中的“双重检验锁”,即在生成订单记录,再次判断一下“当前用户是否已经真的没有抢购过该商品”!

在后面的篇章中,我们将开始搬上“中间件”这一利器,并结合本文所介绍Sql的优化和调整后的代码,彻底解决高并发压力测试的场景下出现的“库存超卖”、“重复秒杀”等乱七八糟的问题!

相关视频教程可私信咨询。


推荐阅读:

Java商城秒杀系统的设计与实战教程(SpringBoot版)

Java秒杀系统实战系列-构建SpringBoot多模块项目

Java秒杀系统实战系列-商品秒杀代码实战

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码