RocketMQ学习(3) 秒杀实战

学习完RocketMQ的用法,现在用它来做一个简单的秒杀项目练练手。

关于秒杀,我之前其实有专门的学习过其中的一些业务逻辑和常见问题,我在这篇博客中有写过多并发场景下的秒杀场景,需要考虑哪些问题?也可以学习一下

除了RocketMQ,本文还需要会springBoot + Redis + Mysql的基本使用。

目录

  • 前置知识
    • QPS、jmeter压测
    • 一般的秒杀架构如何设计
    • 本项目结构设计
    • 数据库准备
  • 接收用户秒杀服务
    • pom和配置文件
    • SeckillController
  • 处理秒杀服务(重点)
    • pom和配置文件
    • Mysql、Redis数据同步
    • 创建秒杀监听
      • 方案一 在事务外面加锁
        • 先查库存再减带来的并发问题
      • 方案二 分布式锁 - mysql(行锁)
      • 方案三 分布式锁 - redis setnx
        • 方案三 redis分布式锁优化

前置知识

QPS、jmeter压测

QPS:每秒处理请求的数量。tomcat一般QPS是多少呢?大家说的500?我们看一下tomcat默认是多少个线程:

在这里插入图片描述

boot 默认是200个线程 假设一个请求50ms 1个线程1s能处理20次 20*200 =4000qps
4000也是理论数值,线程切换需要时间,请求进来时的处理也需要时间,所以是<4000的

我们启动个boot服务,写两个接口测试一下:

@RestController
public class QpsTestController {
   

    /**
     * 
     * @return
     */
    @GetMapping("test")
    public String qpsTest() {
   
        return "ok";
    }


    @GetMapping("test2")
    public String qpsTest2() {
   
        // dosth. 处理处理 操作数据库 操作redis ....  假设为50ms
        try {
   
            Thread.sleep(50L);
        } catch (InterruptedException e) {
   
            e.printStackTrace();
        }
        return "ok";
    }
}

用jmeter压测一下,这个软件用过吧,没用过也没关系,很好上手,下载后在bin目录,双击jmeter.bat启动,Zoom in放大字体,还可以选中文。

在这里插入图片描述

在这里插入图片描述

在默认的Test Plan加一个线程组:

在这里插入图片描述

5000个线程1s内循环2次,所以1s内有10000个线程。

在这里插入图片描述

然后Test Plan添加Http请求:

在这里插入图片描述

在这里插入图片描述

再搞个采样的数据监测器,取结果。在Http请求里加:

在这里插入图片描述

然后启动就会开始打请求了。当然我们这里压测和被压测的都在同一台电脑肯定是不准的。
在这里插入图片描述

像我这种异常率很高的,那数据没有参考价值,qps都测出来15000了,异常率要低于0.5%才有参考价值,要点击下面的清除按钮再启动,一定要清楚,否则指标是平均值。
在这里插入图片描述

然后是test2接口测试,因为是一个电脑测试,异常率太高,正常测试的话就是小于4000的一个值了。

在这里插入图片描述

在这里插入图片描述


根据经验的话,如果tomcat的线程数设置为默认的200,如果一个接口的处理时间很短,在10ms内,那么QPS大概在4k左右,如果接口时间在50ms内,那么QPS大概在2k左右。直观的感受就是处理时间越短,QPS越大,可以自己尝试一下,然后也可以修改一下tomcat线程数尝试一下。




一般的秒杀架构如何设计


根据上一节的经验法则,一个tomcat也就支持2k的qps,代码写得不好可能2k都没有。
那如果是1w/s的请求来了怎么办呢?可以集群部署tomcat,然后用nginx来做负载均衡,但是nginx本身也就顶得住5~10w/s的请求,一般也就5w左右,所以一个nginx也就能配大概25个tomcat。

在这里插入图片描述



那么如果请求QPS大于5w,是20w/s咋办呢,底层是可以堆无数个tomcat,但是nginx也顶不住了,nginx是中心化的方案,所有的请求都要经过它去做负载均衡。而且nginx也是做不了集群的,中心化怎么做集群,就算做了也是需要一个nginx来顶住所有请求的,总得有个入口吧?

在这里插入图片描述



上面的方案不合理,那20w/s的请求咋办呢?入口让硬件来顶,对外提供一个虚拟ip,用Lvs或者F5这样的机器做入口,它能顶30w/s的QPS。

在这里插入图片描述

LVS是一个开源的负载均衡软件,基于Linux内核,可以将网络流量分发到多个后端服务器,实现高可用性和高性能。
F5是一种硬件负载均衡设备,广泛应用于企业级网络环境中。性能要比LVS更高,价格更贵。



那么如果QPS是100w/s呢?现在还没有能顶100w/s的硬件,现在大型的购物平台高峰期可能都是千万级的QPS了,怎么弄呢?做流量分发,比如优惠券,可以分成不同地区的。具体实现可以使用域名–DNS轮询策略,一个域名下面对应了很多个IP,不同的IP对应不同地区的机房,把流量分散开来。

在这里插入图片描述



然后我们写这个秒杀项目还接触不到这些架构设计,写这个秒杀项目的核心目的还是一开始的问题,尽量把每一个接口请求的处理时间给压缩,提高单tomcat的QPS,承受更大的并发量。那如何优化呢——关键是能异步就异步,这就是学完了RocketMQ来写秒杀的原因。

下图是一些后端代码层面优化的一些方法,其实优化方法有很多很多,前端、网络传输、服务端、应用层各种各样的优化方法,比如如果真的做秒杀,前端也会帮我们做限流分流,比如前端可能会搞人际校验,验证码、拼图之类的。

在这里插入图片描述





本项目结构设计

那最后说了这么多,我们项目的结构如何设计,如下图,买东西要先判断库存,如果直接查数据库效率太低,加入redis基于内存提高IO效率,秒杀开始之前数据库的库存数量先预同步到redis,用redis做预扣减,redis理论支持11w读、8w写,真正能达到8w读、6w写。

库存减成功了之后要操作数据库,但是商品种类很多,比如10w件商品在秒杀,操作数据库太慢了,可以将这个操作异步化。用户下单是一个服务(seckill-web),数据库操作(seckill-service)是一个服务,通过rocketmq来解耦。

然后消息消费,即数据库操作也是需要时间的,所以用户也不能立马看到效果,使用异步通知,或者让用户一会再去查看结果。

然后还有一个问题,秒杀场景经常有一个逻辑是一个用户只能对一件商品抢一次,那么这个工作主要是去重,可以通过mysql去重表,但是它不适合大量并发的场景,所以还是通过redis,它的setnx命令也天然支持去重。

在这里插入图片描述



综上,技术选型:springBoot + Redis + Mysql + RocketMq + Security(后期登录可以加上) …
设计: (抢优惠券…)
设计seckill-web接收处理秒杀请求
设计seckill-service处理秒杀真实业务的

部署细节:
用户量: 50w
日活量: 1w-2w 1%-5%
qps: 2w+

如何知道自己的接口有多少qps。方法一:代码统计,自己log打印,统计同一分钟内有多少请求,分布式则=机器台数*单台QPS
方法二,看nginx(access.log),它会记录所有请求,可以写个脚本统计一分钟内某个接口被访问了多少次
方法三,市面上一些监控工具比如阿尔萨斯
在这里插入图片描述

几台服务器(什么配置):8C16G 4台 seckill-web : 4台 seckill-service 2台
带宽: 100M

技术要点:
1.通过redis的setnx对用户和商品做去重判断,防止用户刷接口的行为
2.每天晚上8点通过定时任务 把mysql中参与秒杀的库存商品,同步到redis中去,做库存的预扣减,提升接口性能
3.通过RocketMq消息中间件的异步消息,来将秒杀的业务异步化,进一步提升性能
4.seckill-service使用并发消费模式,并且设置合理的线程数量,快速处理队列中堆积的消息
5.使用redis的分布式锁+自旋锁,对商品的库存进行并发控制,把并发压力转移到程序中和redis中去,减少db压力
6.使用声明式事务注解Transactional,并且设置异常回滚类型,控制数据库的原子性操作
7.使用jmeter压测工具,对秒杀接口进行压力测试,在8C16G的服务器上,qps2k+,达到压测预期
8.使用sentinel的热点参数限流规则,针对爆款商品和普通商品的区别,区分限制



数据库准备

先准备一个数据库,设计了一个商品表和订单表,用户表没有设计问题不大后面传进来就行了。

在这里插入图片描述

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for goods
-- ----------------------------
DROP TABLE IF EXISTS `goods`;
CREATE TABLE `goods`
(
    `id`          int(11)                                                       NOT NULL AUTO_INCREMENT,
    `goods_name`  varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
    `price`       decimal(10, 2)                                                NULL DEFAULT NULL,
    `stocks`      int(255)                                                      NULL DEFAULT NULL,
    `status`      int(255)                                                      NULL DEFAULT NULL,
    `pic`         varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
    `create_time` datetime(0)                                                   NULL DEFAULT NULL,
    `update_time` datetime(0)                                                   NULL DEFAULT NULL,
    PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
  AUTO_INCREMENT = 4
  CHARACTER SET = utf8mb4
  COLLATE = utf8mb4_unicode_ci
  ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of goods
-- ----------------------------
INSERT INTO `goods`
VALUES (1, '小米12s', 4999.00, 1000, 2, 'xxxxxx', '2023-02-23 11:35:56', '2023-02-23 16:53:34');
INSERT INTO `goods`
VALUES (2, '华为mate50', 6999.00, 10, 2, 'xxxx', '2023-02-23 11:35:56', '2023-02-23 11:35:56');
INSERT INTO `goods`
VALUES (3, '锤子pro2', 1999.00, 100, 1, NULL, '2023-02-23 11:35:56', '2023-02-23 11:35:56');
-- ----------------------------
-- Table structure for order_records
-- ----------------------------
DROP TABLE IF EXISTS `order_records`;
CREATE TABLE `order_records`
(
    `id`          int(11)                                                       NOT NULL AUTO_INCREMENT,
    `user_id`     int(11)                                                       NULL DEFAULT NULL,
    `order_sn`    varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
    `goods_id`    int(11)                                                       NULL DEFAULT NULL,
    `create_time` datetime(0)                                                   NULL DEFAULT NULL,
    PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  CHARACTER SET = utf8mb4
  COLLATE = utf8mb4_unicode_ci
  ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;


接收用户秒杀服务

pom和配置文件

pom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

隐藏 IP 地址的重要性是什么?

在当今的数字时代&#xff0c;保护我们的在线身份至关重要。从保护个人信息到保护隐私&#xff0c;互联网用户越来越多地寻求增强在线安全性的方法。保持匿名和保护敏感数据的一个关键方面是隐藏您的 IP 地址。在这篇博文中&#xff0c;我们将深入探讨隐藏 IP 地址的重要性&…

项目:消息队列的前置知识

文章目录 写在前面环境安装 Protubuf基本介绍 Muduo基本介绍 SQLite3异步操作实现线程池 本篇是对于一个仿RabbitMQ实现的消息队列项目的前置知识的说明文档 写在前面 环境安装 Protubuf 基本介绍 项目所需要的比较重要模块有Protubuf模块&#xff0c;那么下面先对于这个模…

28 _ WebComponent:像搭积木一样构建Web应用

在上一篇文章中我们从技术演变的角度介绍了PWA&#xff0c;这是一套集合了多种技术的理念&#xff0c;让浏览器渐进式适应设备端。今天我们要站在开发者和项目角度来聊聊WebComponent&#xff0c;同样它也是一套技术的组合&#xff0c;能提供给开发者组件化开发的能力。 那什么…

微信支付(可复用)

3.1微信支付 本项目选择小程序支付 参考&#xff1a;产品中心 - 微信支付商户平台微信支付商户平台提供各类支付产品满足商家通过微信支付收款的需求&#xff1b;平台提供智慧经营&#xff0c;现金红包&#xff0c;代金券等运营工具&#xff0c;助力商家更好的玩转营销&#x…

重生奇迹mu格斗家介绍

出生地&#xff1a;勇者大陆 性 别&#xff1a;男 擅 长&#xff1a;近距离攻击、技能以PVP为主战斗风格 转 职&#xff1a;格斗大师&#xff08;3转&#xff09; 介 绍&#xff1a;以PVP战斗模式为主的格斗家&#xff0c;依角色养成配点不同&#xff0c;可发展成以力量体力…

恒创科技:无法与服务器建立安全连接怎么解决?

在使用互联网服务时&#xff0c;有时会出现无法与服务器建立安全连接的问题&#xff0c;此错误消息通常出现在尝试访问需要安全连接的网站(例如使用 HTTPS 的网站)时&#xff0c;这可能是由于多种原因造成的&#xff0c;以下是一些常见的解决方法&#xff0c;帮助你解决问题。 …

AI来了,产品经理该怎样面对它?

AI终于来了&#xff0c;我们一方面期待着它可能给我们生活带来的变化&#xff0c;另一方面又担忧它可能带给我们巨大的风险和挑战。 AI带来的影响 AI不确定性的风险有很多&#xff0c;例如有人关注它是否成为“奥创”&#xff0c;但对我们大多数人来说这样的风险还很遥远&#…

Java1.8+ idea hbuilder+ uniapp、vue上门家政小程序APP源码开发

Java1.8 idea hbuilder uniapp、vue上门家政小程序APP源码开发 家政服务系统是一种专为家庭提供全方位服务的综合性系统。该系统通过整合多种服务功能和智能化管理&#xff0c;旨在提高家庭生活的质量和效率。 家政服务系统技术开发环境&#xff1a; 技术架构&#xff1a;spri…

怎么制作在线研学活动报名系统?教你快速搞定

易查分小程序&#xff1a;提升研学活动体验&#xff0c;智慧管理新选择 在教育多元化的今天&#xff0c;学校组织的研学活动可以为学生提供更多实践学习、探索世界的机会。不过&#xff0c;对于老师来说&#xff0c;活动的报名和管理常常比较复杂&#xff0c;导致工作量增加。…

工业相机识别电路板元器件:彩色与黑白的区别

工业相机用于识别电路板上的元器件时&#xff0c;选择彩色相机或黑白相机取决于具体应用需求和条件。彩色相机能提供更丰富的信息&#xff0c;但处理复杂度较高&#xff1b;黑白相机则在处理速度和精度上具有优势。理解它们的区别和各自的优缺点&#xff0c;有助于在具体项目中…

软件功能测试内容简析,第三方软件测试机构进行功能测试的好处

软件功能测试是指对软件产品的各项功能进行验证和确认的过程。它是软件开发过程中非常重要的一环&#xff0c;通过对软件的功能进行全面测试&#xff0c;可以确保软件在交付给用户之前达到预期的质量要求。 在进行功能测试时&#xff0c;需要包括以下几个方面的测试内容&#…

docker运行centos提示Operation not permitted

1、在docker中运行了centos7镜像 2、进入到centos容器中使用systemctl命令时提示 systemctl Failed to get D-Bus connection: Operation not permitted 3、解决办法 在运行centos镜像的时候加上--privileged参数 4、附上docker官网命令说明截图

驱动芯片退饱和保护(DESAT)

驱动芯片退饱和保护&#xff08;DESAT&#xff09; 1.概述2.短路能力评估3.驱动芯片的退饱和保护功能介绍3.1 退饱和工作原理3.2 退饱和电路的关键组成和影响因素 4.驱动芯片的退饱和保护功能的调试4.1 如何增加 DESAT 充电电流4.2 如何调整 DESAT 阈值电压4.3 如何使用 OC 功能…

Chrome 调试技巧

1. alert 在最早的时候&#xff0c;javascript 程序员调试代码都是通过 alert 进行&#xff0c;但 alert 会让整个程序被打断&#xff0c;并且还有一个很大的缺点&#xff0c;调试完成之后&#xff0c;如果忘记将 alert 删除 or 注释掉&#xff0c;导致别人访问该页面时会莫名…

基于System-Verilog实现DE2-115开发板驱动HC_SR04超声波测距

目录 前言 一、SystemVerilog——下一代硬件设计语言 与Verilog关系 与SystemC关系 二、实验原理 2.1 传感器概述&#xff1a; 2.2 传感器引脚 2.3 传感器工作原理 2.4 整体测距原理及编写思路 三、System-Verilog文件 3.1 时钟分频 3.2 超声波测距 3.3 数码管驱动…

【EI会议/稳定检索】2024年机械、传感与自动控制国际会议(MSAC 2024)

2024 International Conference on Machinery, Sensing, and Automatic Control 2024年机械、传感与自动控制国际会议 【会议信息】 会议简称&#xff1a;MSAC 2024 大会地点&#xff1a;中国贵阳 会议官网&#xff1a;www.msaciac.com 会议邮箱&#xff1a;msacsub-paper.com…

TMS320F280049 ECAP模块--总览(0)

ECAP 特性&#xff1a; 4个32bit的事件时间戳寄存器&#xff1b; 4个连续时间戳捕获事件的边沿极性可选上升沿、下降沿 4个事件中每个都能触发中断 4个事件都能做单词触发 可以连续捕获4个事件 绝对的捕获时间戳 差异模式捕获 不使用捕获模式时&#xff0c;可以配置输出…

【设计模式】JAVA Design Patterns——Factory Method(虚拟构造器模式)

&#x1f50d;目的 为创建一个对象定义一个接口&#xff0c;但是让子类决定实例化哪个类。工厂方法允许类将实例化延迟到子类 &#x1f50d;解释 真实世界例子 铁匠生产武器。精灵需要精灵武器&#xff0c;而兽人需要兽人武器。根据客户来召唤正确类型的铁匠。 通俗描述 它为类…

esp32芯片选型网页链接

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/bd340b1360dc45ec9a4286f64c95b39d.png esp32芯片选型网页链接

采用C#、Python和Qt开发上位机好看的界面也不是多的事儿

采用C#、Python和Qt开发上位机好看的界面也不是多的事儿