一、慢查询分析

慢查询分析是通过开启慢查询日志开关、然后执行某个sql超过了配置的查询最大时间会将这条sql记录到慢查询日志中,以便我们开发人员进行分析检查查询慢的原因,方便进行sql优化。(面试时我们可以编一个故事、我们在做项目中是如何进行sql优化的、比如我们可以假设在商品展示中发现商品列表加载太慢、然后通过使用慢查询分析发现是查询商品活动信息sql语句超时、经过分析是查询没有使用索引、优化后使用索引提高了页面的加载速度。)

打开慢查询日志开关

有两种方式一种是设置参数、一种是修改配置文件。这里使用设置参数、详细看下图分析

测试慢查询日志

执行一条select sleep(3);表示睡三秒、刚刚设置了慢查询日志的最大查询时间为1秒所以这条语句会超时并被慢查询日志记录到日志中。

二、用户下单和秒杀

超卖和少卖问题(面试重点)

下单操作会涉及到库存扣减、扣减库存一般发生在下单和付款时、在高并发情况下涉及到而两个问题超卖少卖。这在面试中也是常问的问题

  1. 下单时扣减库存:比如有100件商品、秒杀时有100人下了单,这时候库存已经没有了商品、理论卖出去了100件,但实际付款的只有80人,另外20人没有付款,实际只卖出去了80件,还有20件商品没有卖出去,但库存表中的库存数已经为0了。这就出现了少卖问题。
    怎么解决少卖问题呢、就是通过超时未付款自动取消订单、然后回退库存数。
  2. 付款时扣减库存:还是假如有100件商品、由于是付款时扣减库存、所以就算有100人下单商品没有付款的话还是可以继续下单的,假如有150个人下了单、但只能有前100个付款的人才能购买成功后50个人无法购买,这样给人的体验是很差的,明明已经抢到了。这就是超卖问题

本项目中使用的是下单时扣减库存的方法。

下单操作前端

在商品列表栏单击商品、进入详情页面
在详情页点击购买即可完成下单
由前端页面可知、请求的后端接口是http://127.0.0.1:8080/order/create

后端实现

数据库表解读

  1. order_info表:用于保存生成订单的表。表记录的信息有用户id、商品id、活动id创建时间等。
    需要注意的是这里订单表冗余记录了商品的单价、目的是这是活动的单价、商品的单价是有可能改变的。
    还有就是订单信息的id,比如‘20210807000000000000’前八位20210807表示的是订单日期的年月日、后面表示的就是订单的流水号。这么做的原因是当订单表未来是会一张很大很大的表、一般情况下会进行数据的拆分、比如我们用京东淘宝会有最近订单和历史订单、历史订单是显然会放在另一张表中、因为如果全部保存在这张下单用的订单表中很显然内存很容易不够用的,我们可以根据日期将订单进行拆分、这时候id中的前八位就起到作用了进行拆分时就可以走索引提高效率了,假设不是这样的话就只能使用后面的日期进行拆分那将会很慢。
    2. serial_number表:保存订单表中的流水号自增id的索引增到哪了。
    name:表示的是业务名。
    value:表示的是索引值增加到哪了。
    step:是步长、每次索引增加的大小。

    对应的控制处理器层
    根据代码可知、前端会传过来商品id、商品数量、商品活动的id。先通过session获取user对象、然后调用service层的createOrder创建订单方法,将userid、商品id、商品活动id传过去。

    对应的service层
    service代码比较多、注释已经很明白,先是验证商品数量、活动id、用户、商品等是否合理,防止黑客假数据攻击。校验都通过后、就会直接扣减库存、生成订单,最后更新销量数据。
 @Override@Transactionalpublic Order createOrder(int userId, int itemId, int amount, Integer promotionId) {// 校验参数if (amount < 1 || (promotionId != null && promotionId.intValue() <= 0)) {throw new BusinessException(PARAMETER_ERROR, "指定的参数不合法!");}// 校验用户User user = userService.findUserById(userId);if (user == null) {throw new BusinessException(PARAMETER_ERROR, "指定的用户不存在!");}// 校验商品Item item = itemService.findItemById(itemId);if (item == null) {throw new BusinessException(PARAMETER_ERROR, "指定的商品不存在!");}// 校验库存int stock = item.getItemStock().getStock();if (amount > stock) {throw new BusinessException(STOCK_NOT_ENOUGH, "库存不足!");}// 校验活动if (promotionId != null) {if (item.getPromotion() == null) {throw new BusinessException(PARAMETER_ERROR, "指定的商品无活动!");} else if (!item.getPromotion().getId().equals(promotionId)) {throw new BusinessException(PARAMETER_ERROR, "指定的活动不存在!");} else if (item.getPromotion().getStatus() == 1) {throw new BusinessException(PARAMETER_ERROR, "指定的活动未开始!");}}// 扣减库存boolean successful = itemService.decreaseStock(itemId, amount);if (!successful) {throw new BusinessException(STOCK_NOT_ENOUGH, "库存不足!");}// 生成订单Order order = new Order();order.setId(this.generateOrderID());order.setUserId(userId);order.setItemId(itemId);order.setPromotionId(promotionId);order.setOrderPrice(promotionId != null ? item.getPromotion().getPromotionPrice() : item.getPrice());order.setOrderAmount(amount);order.setOrderTotal(order.getOrderPrice().multiply(new BigDecimal(amount)));order.setOrderTime(new Timestamp(System.currentTimeMillis()));orderMapper.insert(order);// 更新销量itemService.increaseSales(itemId, amount);return order;}

需要注意的是订单id是怎么生成的,id是通过service层的generateOrderID()生成的,看代码

    /*** 格式:日期 + 流水* 示例:20210123000000000001** @return*/@Transactional(propagation = Propagation.REQUIRES_NEW)private String generateOrderID() {StringBuilder sb = new StringBuilder();// 拼入日期sb.append(Toolbox.format(new Date(), "yyyyMMdd"));// 获取流水号SerialNumber serial = serialNumberMapper.selectByPrimaryKey("order_serial");Integer value = serial.getValue();// 更新流水号serial.setValue(value + serial.getStep());serialNumberMapper.updateByPrimaryKey(serial);// 拼入流水号String prefix = "000000000000".substring(value.toString().length());sb.append(prefix).append(value);return sb.toString();}

根据代码可知通过一个stringBuilder拼接字符串

  1. 先是拼接格式化当前日期的年月日格式是yyyyMM、
  2. 然后获取serial_number表中的索引序号也就是流水号、
  3. 获取后更新流水号,步长是serial_number中的step字段的值
  4. 使用substring除去value长度、拼接value到prefix后面

对应的daomapper()层
其他都没什么好说的、都是一些常规的增删改查。
需要注意的是在查询流水号时增加了一个for update排它锁、目的是防止在并发情况下会发生读到同一个数据的情况、进而导致流水订单id一样的情况

总结

面试时这一块主要会问到、mysql索引、事务相关的知识,要重点去看下这两块的八股文。

(秒杀项目) 4.4 用户下单与秒杀相关推荐

  1. 秒杀情况下,用户下单扣除库存创建订单之后,迟迟不付款,时间到了自动取消订单(思路)

    秒杀情况下,用户下单扣除库存创建订单之后,迟迟不付款,时间到了自动取消订单 解决方案1. 使用redis实现 1.下单之后把生成分布式全局唯一id,把订单id放进redis中,设置一个过期时间 2.定 ...

  2. 秒杀项目(前后端分离)

    1P/11P项目开篇 技术点总结 1.安装开发工具 2P/11p 项目架构介绍 常见的请求:返回前端页面HTML:Model+HTML模板 ajax异步请求:返回json数据[返回特定格式的字符串只返 ...

  3. 预约活动(秒杀)项目中如何高效的保证下单交易成功?保证redis,mysql的最终一致性?

    预约活动(秒杀)项目中如何高效的保证下单交易成功?保证redis,mysql的最终一致性? 前言 `在秒杀项目中,秒杀下单的过程中都需要经历四步,分别为: 1.校验下单状态,商品是否存在,用户是否合法 ...

  4. 【商城秒杀项目】-- 流量削峰应该怎么做

    如果你看过秒杀系统的流量监控图的话,你会发现它是一条直线,在秒杀开始那一秒是一条很直很直的线,这是因为秒杀请求在时间上高度集中于某一特定的时间点.这样一来,就会导致一个特别高的流量峰值,它对资源的消耗 ...

  5. 小红书-内卖秒杀项目总结

    文章目录 一.背景介绍 二.鸣谢 三.为什么会决定参与内卖? 四.第一次内卖 1. 前言 2. 技术方案设计 3.内卖过程中遇到的问题 4.回顾总结 四.第二次内卖 1.前言 2.技术方案设计 3.回 ...

  6. 秒杀项目05-页面优化技术

    秒杀项目05-页面优化技术 1. 页面缓存+URL缓存+对象缓存 1.1 页面缓存 1.2 URL缓存 1.3 对象缓存(更细粒度的缓存) 2. 页面静态化,前后端分离 1. 常用技术AngularJ ...

  7. SpringBoot学习+秒杀项目

    目录一 ~ 六来源:GitHub 一.项目简介 1.商品列表页获取秒杀商品列表 2.进入商品详情页获取秒杀商品详情 3.秒杀开始后进入下单确认页下单并支付成功 二.应用springboot完成基础项目 ...

  8. 秒杀项目如何防止超卖问题

    防止超卖问题主要是在数据库上做文章 问题1.商品数量减为负数 在数据库插入操作时,判断stock_count的大小,如果大于0才允许减库存 问题2.一个用户重复秒杀 在miaosha_order上加基 ...

  9. 针对秒杀项目做的一些优化

    秒杀 业务逻辑 数据库的设计 一些全局配置 JSR303参数验证(手机号) 登录 分布式Session问题? 秒杀 整体流程 优化 UserArgumentResolver 和AccessInterc ...

  10. 基于SpringBoot+Mybatis框架的商城秒杀项目总结

    最近做了一个以SpringBoot+Mybaits为框架前后端分离的商城秒杀项目,主要使用的工具是Idea和Maven,SpringBoot是一个功能十分强大的框架集合,里面包含了很多的框架. 工程的 ...

最新文章

  1. 获取线程中抛出的异常信息
  2. 初始化列表的使用(十五)
  3. 怎么自学python自动化测试-python自动化测试如何自动生成测试用例?
  4. OpenCV用代码解释单应性的基本概念
  5. php 不支持无符号整数,是否可以使用大型无符号int64而不会在PHP中失去精度?
  6. NOIP2020洛谷P7115:移球游戏(分治)
  7. 【原理+实战+视频+源码】docker映射端口教程
  8. azure linux 磁盘,在Azure Linux VM中,还有什么?什么磁盘收费?
  9. 全面认识Eclipse中JVM内存设置(转)
  10. Cocos2d-3.x Android环境搭建
  11. Oracle 12C 创建用户失败 - ORA-65096 invalid common user or role name
  12. java 封闭类型_Java并发之线程封闭
  13. 14.1宽屏Intel集显调分辨率:无解
  14. Unity高亮插件HighlightingSystem使用
  15. 202102 sqlplus command not found 注意切换用户
  16. 【oracle】中文数字转阿拉伯数字
  17. 高等数学第七版总结(同济大学版)
  18. 大小限制_微信传文件有大小限制?PPT太大怎么传?PPT自带三大压缩功能
  19. 非结构化数据的定义及处理方法
  20. 快手自动操作学习参考

热门文章

  1. 20150820-Linux命令概述及一些基本命令
  2. Oracle sga、pga介绍改动
  3. 深度揭秘 如何将PDF转换成Word的技巧
  4. 如何应对团购鼻祖Groupon的“***”
  5. 7.凤凰架构:构建可靠的大型分布式系统 --- 从类库到服务
  6. 1.Prometheus 监控技术与实践 --- 云计算时代的监控系统
  7. 25.MySQL sql_mode
  8. LoadRunner监控SQLServer
  9. 应用安全-安全设备-Waf系列-软Waf-D盾
  10. 单链表java实现及相关操作(版本1)