欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

程序员文章站 2024-01-20 15:45:22
...

原理:

秒杀与其他业务最大的区别在于,在秒杀的瞬间,系统的并发量和吞吐量会非常大,与此同时,网络的流量也会瞬间变大。

对于网络流量瞬间变大问题,最常用的办法就是将页面静态化,也就是我们常说的前后端分离。把静态页面直接缓存到用户的浏览器中,当用户需要获取数据时,就从服务端接口动态获取。这样会大大节省网络的流量,如果再加上CDN优化,一般都不会有大问题。

对于系统并发量变大问题,这里的核心在于如何在大并发的情况下保证数据库能扛得住压力,因为大并发的瓶颈在于数据库。如果用户的请求直接从前端传到数据库,显然,数据库是无法承受几十万上百万甚至上千万的并发量的。因此,我们能做的只能是减少对数据库的访问。例如,前端发出了100万个请求,通过我们的处理,最终只有10个会访问数据库,这样就会大大提升系统性能。再针对秒杀这种场景,因为秒杀商品的数量是有限的,因此这种做法刚好适用。

那么具体是如何来减少对数据库的访问的呢?

假如,某个商品可秒杀的数量是10,那么在秒杀活动开始之前,把商品的ID和数量加载到Redis缓存。当服务端收到请求时,首先预减Redis中的数量,如果数量减到小于0时,那么随后的访问直接返回秒杀失败的信息。也就是说,最终只有10个请求会去访问数据库。

如果商品数量比较多,比如1万件商品参与秒杀,那么就有1万*10=10万个请求并发去访问数据库,数据库的压力还是会很大。这里就用到了另外一个非常重要的组件:消息队列。我们不是把请求直接去访问数据库,而是先把请求写到消息队列中,做一个缓存,然后再去慢慢的更新数据库。这样做之后,前端用户的请求可能不会立即得到响应是成功还是失败,很可能得到的是一个排队中的返回值,这个时候,需要客户端去服务端轮询,因为我们不能保证一定就秒杀成功了。当服务端出队,生成订单以后,把用户ID和商品ID写到缓存中,来应对客户端的轮询就可以了。

这样处理以后,我们的应用是可以很简单的进行分布式横向扩展的,以应对更大的并发。

当然,秒杀系统还有很多要处理的事情,比如限流防刷、分布式Session等等。

1.搭建项目环境

下方提供了安装工具的博客

1.1 安装RabbitMQ

https://blog.csdn.net/m0_37034294/article/details/82839494

2.2 安装Redis+RedisDesktopManager

https://blog.csdn.net/qq_39135287/article/details/82686837

2.3 Jmeter压力测试工具

https://blog.csdn.net/liuyanh2006/article/details/82494548

2.4 创建数据库表结构

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)
实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

注意:请将主键设为自动增长

2.项目代码

1.创建一个springboot项目,启动器可先不选择,下方直接放pom.xml文件,cv即可。


    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.8.1</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.7.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.1.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
    </dependency>
    <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper-spring-boot-starter</artifactId>
        <version>2.0.3-beta1</version>
    </dependency>
    <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper</artifactId>
        <version>4.0.0</version>
    </dependency>

2.配置application.properties文件


spring.devtools.restart.enabled=false
##配置数据库连接
spring.datasource.username=root
spring.datasource.password=root
server.port=8443
spring.datasource.url=jdbc:mysql://localhost:3306/myredis?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&allowMultiQueries=true
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

##配置rabbitmq连接
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

#JPA Configuration:
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect

##配置连接redis --都记得打开服务
spring.redis.host=localhost
spring.redis.port=6379 
spring.redis.jedis.pool.max-active=1024
spring.redis.jedis.pool.max-wait=-1s
spring.redis.jedis.pool.max-idle=200
spring.redis.password=123456
  1. 新建pojo包,添加实体类

    本次数据库操作方面使用了tkmybatis框架,所以实体类我们需要用到JPA的注解,来实现映射关系。

    
    import java.io.Serializable;
    import lombok.Data;
    import javax.persistence.Column;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.Table;
    @Data
    @Table(name = "t_order")
    public class Order implements Serializable {
        private static final long serialVersionUID = -8867272732777764701L;
    
        @Id
        @Column(name = "id")
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(name = "order_name")
        private String order_name;
    
        @Column(name = "order_user")
        private String order_user;
    }
    
    
    import lombok.Data;
    import javax.persistence.Column;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.Table;
    import java.io.Serializable;
    @Table(name = "stock")
    @Data
    public class Stock implements Serializable {
        private static final long serialVersionUID = 2451194410162873075L;
    
        @Id
        @Column(name = "id")
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(name = "name")
        private String name;
    
        @Column(name = "stock")
        private Long stock;
    }
    
  2. 配置tkmybatis的接口

​ 4.1 需要通过继承它来实现数据库操作

  1. 2新建名为base的包,在base下面新建service的接口

  2. 3新建GenericMapper接口

import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;

public interface GenericMapper<T> extends Mapper<T>, MySqlMapper<T> {
}

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

  1. 新建mapper层

OrderMapper.java

import com.demo.base.service.GenericMapper;
import com.demo.pojo.Order;

public interface OrderMapper extends GenericMapper<Order> {
    void insertOrder(Order order);
}
    

StockMapper.java

import com.demo.base.service.GenericMapper;
import com.demo.pojo.Stock;

public interface StockMapper extends GenericMapper<Stock> {
}

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

  1. 编写RabbitMQ和redis的配置类
    新建config包,新建redis和RabbitMQ的类
package com.demo.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.ExchangeBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyRabbitMQConfig {

    //库存交换机
    public static final String STORY_EXCHANGE = "STORY_EXCHANGE";

    //订单交换机
    public static final String ORDER_EXCHANGE = "ORDER_EXCHANGE";

    //库存队列
    public static final String STORY_QUEUE = "STORY_QUEUE";

    //订单队列
    public static final String ORDER_QUEUE = "ORDER_QUEUE";

    //库存路由键
    public static final String STORY_ROUTING_KEY = "STORY_ROUTING_KEY";

    //订单路由键
    public static final String ORDER_ROUTING_KEY = "ORDER_ROUTING_KEY";
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }
    //创建库存交换机
    @Bean
    public Exchange getStoryExchange() {
        return ExchangeBuilder.directExchange(STORY_EXCHANGE).durable(true).build();
    }
    //创建库存队列
    @Bean
    public Queue getStoryQueue() {
        return new Queue(STORY_QUEUE);
    }
    //库存交换机和库存队列绑定
    @Bean
    public Binding bindStory() {
        return BindingBuilder.bind(getStoryQueue()).to(getStoryExchange()).with(STORY_ROUTING_KEY).noargs();
    }
    //创建订单队列
    @Bean
    public Queue getOrderQueue() {
        return new Queue(ORDER_QUEUE);
    }
    //创建订单交换机
    @Bean
    public Exchange getOrderExchange() {
        return ExchangeBuilder.directExchange(ORDER_EXCHANGE).durable(true).build();
    }
    //订单队列与订单交换机进行绑定
    @Bean
    public Binding bindOrder() {
        return BindingBuilder.bind(getOrderQueue()).to(getOrderExchange()).with(ORDER_ROUTING_KEY).noargs();
    }
}
package com.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
    // 配置redis得配置详解
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(redisConnectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setHashKeySerializer(new GenericJackson2JsonRedisSerializer());
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }
}

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

  1. 编写service层
    新建service包以及impl包,这里只提供实现类
import com.demo.mapper.OrderMapper;
import com.demo.pojo.Order;
import com.demo.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Override
    public void createOrder(Order order) {
        orderMapper.insert(order);
    }
}
package com.demo.service.impl;
import com.demo.mapper.StockMapper;
import com.demo.pojo.Stock;
import com.demo.service.StockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;
import java.util.List;
@Service
public class StockServiceImpl implements StockService {
    @Autowired
    private StockMapper stockMapper;
    // 秒杀商品后减少库存
    @Override
    public void decrByStock(String stockName) {
        Example example = new Example(Stock.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("name", stockName);
        List<Stock> stocks = stockMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(stocks)) {
            Stock stock = stocks.get(0);
            stock.setStock(stock.getStock() - 1);
            stockMapper.updateByPrimaryKey(stock);
        }
    }
    // 秒杀商品前判断是否有库存
    @Override
    public Integer selectByExample(String stockName) {
        Example example = new Example(Stock.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("name", stockName);
        List<Stock> stocks = stockMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(stocks)) {
            return stocks.get(0).getStock().intValue();
        }
        return 0;
    }
}
  1. 继续在 service包下面新建

    MQOrderService.java

package com.demo.service;

import com.demo.config.MyRabbitMQConfig;
import com.demo.pojo.Order;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/*订单的消费队列*/
@Service
@Slf4j
public class MQOrderService {
    @Autowired
    private OrderService orderService;
    /**
     * 监听订单消息队列,并消费
     *
     * @param order
     */
    @RabbitListener(queues = MyRabbitMQConfig.ORDER_QUEUE)
    public void createOrder(Order order) {
        log.info("收到订单消息,订单用户为:{},商品名称为:{}", order.getOrder_user(), order.getOrder_name());
        /**
         * 调用数据库orderService创建订单信息
         */
        orderService.createOrder(order);
    }
}

MQStockService.java

package com.demo.service;

import com.demo.config.MyRabbitMQConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/*消费队列*/
@Service
@Slf4j
public class MQStockService {
    @Autowired
    private StockService stockService;
    /**
     * 监听库存消息队列,并消费
     * @param stockName
     */
    @RabbitListener(queues = MyRabbitMQConfig.STORY_QUEUE)
    public void decrByStock(String stockName) {
        log.info("库存消息队列收到的消息商品信息是:{}", stockName);
        /**
         * 调用数据库service给数据库对应商品库存减一
         */
        stockService.decrByStock(stockName);
    }
}

RedisService.java

**主要用来实现对redis得key和value初始化以及对value得操作** 
package com.demo.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.concurrent.TimeUnit;
@Service
public class RedisService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    /**
     * 设置String键值对
     * @param key
     * @param value
     * @param millis
     */
    public void put(String key, Object value, long millis) {
        redisTemplate.opsForValue().set(key, value, millis, TimeUnit.MINUTES);
    }
    public void putForHash(String objectKey, String hkey, String value) {
        redisTemplate.opsForHash().put(objectKey, hkey, value);
    }
    public <T> T get(String key, Class<T> type) {
        return (T) redisTemplate.boundValueOps(key).get();
    }
    public void remove(String key) {
        redisTemplate.delete(key);
    }
    public boolean expire(String key, long millis) {
        return redisTemplate.expire(key, millis, TimeUnit.MILLISECONDS);
    }
    public boolean persist(String key) {
        return redisTemplate.hasKey(key);
    }
    public String getString(String key) {
        return (String) redisTemplate.opsForValue().get(key);
    }
    public Integer getInteger(String key) {
        return (Integer) redisTemplate.opsForValue().get(key);
    }
    public Long getLong(String key) {
        return (Long) redisTemplate.opsForValue().get(key);
    }
    public Date getDate(String key) {
        return (Date) redisTemplate.opsForValue().get(key);
    }

    /**
     * 对指定key的键值减一
     * @param key
     * @return
     */
    public Long decrBy(String key) {
        return redisTemplate.opsForValue().decrement(key);
    }
}

​ 下面为service包得完整目录

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)
10. 新建controller层,添加SecController.java,包含两种方法,参考下面的代码

```java
import com.demo.config.MyRabbitMQConfig;
import com.demo.pojo.Order;
import com.demo.service.OrderService;
import com.demo.service.RedisService;
import com.demo.service.StockService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@Slf4j
public class SecController {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedisService redisService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private StockService stockService;
    /**
     * 使用redis+消息队列进行秒杀实现
     *
     * @param username
     * @param stockName
     * @return
     */
    @PostMapping( value = "/sec",produces = "application/json;charset=utf-8")
    @ResponseBody
    public String sec(@RequestParam(value = "username") String username, @RequestParam(value = "stockName") String stockName) {

        log.info("参加秒杀的用户是:{},秒杀的商品是:{}", username, stockName);
        String message = null;
        //调用redis给相应商品库存量减一
        Long decrByResult = redisService.decrBy(stockName);
        if (decrByResult >= 0) {
            /**
             * 说明该商品的库存量有剩余,可以进行下订单操作
             */
            log.info("用户:{}秒杀该商品:{}库存有余,可以进行下订单操作", username, stockName);
            //发消息给库存消息队列,将库存数据减一
            rabbitTemplate.convertAndSend(MyRabbitMQConfig.STORY_EXCHANGE, MyRabbitMQConfig.STORY_ROUTING_KEY, stockName);

            //发消息给订单消息队列,创建订单
            Order order = new Order();
            order.setOrder_name(stockName);
            order.setOrder_user(username);
            rabbitTemplate.convertAndSend(MyRabbitMQConfig.ORDER_EXCHANGE, MyRabbitMQConfig.ORDER_ROUTING_KEY, order);
            message = "用户" + username + "秒杀" + stockName + "成功";
        } else {
            /**
             * 说明该商品的库存量没有剩余,直接返回秒杀失败的消息给用户
             */
            log.info("用户:{}秒杀时商品的库存量没有剩余,秒杀结束", username);
            message = "用户:"+ username + "商品的库存量没有剩余,秒杀结束";
        }
        return message;
    }

    /**
     * 实现纯数据库操作实现秒杀操作
     * @param username
     * @param stockName
     * @return
     */
    @RequestMapping("/secDataBase")
    @ResponseBody
    public String secDataBase(@RequestParam(value = "username") String username, @RequestParam(value = "stockName") String stockName) {
        log.info("参加秒杀的用户是:{},秒杀的商品是:{}", username, stockName);
        String message = null;
        //查找该商品库存
        Integer stockCount = stockService.selectByExample(stockName);
        log.info("用户:{}参加秒杀,当前商品库存量是:{}", username, stockCount);
        if (stockCount > 0) {
            /**
             * 还有库存,可以进行继续秒杀,库存减一,下订单
             */
            //1、库存减一
            stockService.decrByStock(stockName);
            //2、下订单
            Order order = new Order();
            order.setOrder_user(username);
            order.setOrder_name(stockName);
            orderService.createOrder(order);
            log.info("用户:{}.参加秒杀结果是:成功", username);
            message = username + "参加秒杀结果是:成功";
        } else {
            log.info("用户:{}.参加秒杀结果是:秒杀已经结束", username);
            message = username + "参加秒杀活动结果是:秒杀已经结束";
        }
        return message;
    }

}
```

11. 编写springboot启动类,对redis进行初始化,**简而言之就是调用我们上面写得方法,新建一个redis缓存,模拟商品信息** 

    ```java
    import com.demo.service.RedisService;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.ApplicationArguments;
    import org.springframework.boot.ApplicationRunner;
    import tk.mybatis.spring.annotation.MapperScan;
    @MapperScan("com.demo.mapper")
    @SpringBootApplication
    public class DemoApplication  implements ApplicationRunner{
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
        @Autowired
        private RedisService redisService;
        /**
         * redis初始化商品的库存量和信息
         * @param args
         * @throws Exception
         */
        @Override
        public void run(ApplicationArguments args) throws Exception {
            redisService.put("watch", 10, 20);
        }
    }
    ```

    12. 至此,代码已全部写完,下图为项目目录,下面进入测试步骤,请检查以上步骤是否出错!

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T5smGH7i-1577175164825)(C:\Users\WuLian\Pictures\1\QQ图片20191224144222.png)]

3.测试项目

  1. 启动springboot项目,并且打开 redis和rabbitmq的服务

  2. 打开Redis Desktop Manager工具,查看是否新建了一个redis :watch

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

  1. 打开我们得JMeter工具

3.1 选择中文

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

3.2 完成中文之后,我们在测试计划右键,添加一个线程组

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

3.3 给这个线程组得数量为40,这个线程组得作用就是模拟40个用户发送请求,去秒杀.然后再在线程组右键,添加一个Http请求,这个就是我们用来发送请求得组件了 

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

3.4 这个请求唯一要说得就是,随机参数了,因为用户名肯定不可能给40个相同得名字,**这边我们利用JMeter给用户名得值为随机数**

点击上方得白色小书本,选择random,1-99得随机数

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

3.5 然后我们把这个函数字符串复制到http得参数上面去

实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

3.6 最后我们在测试计划建一个结果树,查看我们发送请求返回得消息数据
实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)
3.7 点击运行 实现基于SpringBoot+Maven+Mysql+Redis+RabbitMQ 的高并发秒杀系统(限时秒杀)

4.测试结果

直接在run控制台查看运行结果,以及数据库表的变化。

相关标签: redis rabbitmq