当前位置:

首页 > 编程开发 > 怎么使用Springboot+redis+Vue实现秒杀系统

怎么使用Springboot+redis+Vue实现秒杀系统

Redis Assistant
Redis Assistant

Redis Assistant 是一款为Redis设计的高效可视化管理与监控工具,提供多种操作模式,高效处理服务器数据。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

立即下载
¥19
Windows/macOS/Linux 2026-08-22
正版软件 Windows macOS软件 Linux 数据库管理工具

1、Redis简介Redis是一个开源的key-value存储系统。Redis的五种基本类型:String(字符串),list(链表),set(集合),zset(有序集合),hash,stream(Redis5.0后的新数据结构)这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。Redis的应用场景为配合关系型数据库做高速缓存,降低数据库IO需要注意的是,Redis是单线程的,如果一次批量处理命令过多,会造成Redis阻塞或网络拥塞(传输数

本文目录

    1、Redis简介

    Redis是一个开源的key-value存储系统。

    Redis的五种基本类型:String(字符串),list(链表),set(集合),zset(有序集合),hash,stream(Redis5.0后的新数据结构)

    这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。

    Redis的应用场景为配合关系型数据库做高速缓存,降低数据库IO

    需要注意的是,Redis是单线程的,如果一次批量处理命令过多,会造成Redis阻塞或网络拥塞(传输数据量大)

    2、实现代码

    怎么使用Springboot+redis+Vue实现秒杀系统

    pom.xml

    
    
        4.0.0
        
            org.springframework.boot
            spring-boot-starter-parent
            2.2.1.RELEASE
             
        
        org.example
        seckill
        1.0-SNAPSHOT
        
            1.8
        
    
        
            
                org.springframework.boot
                spring-boot-starter-web
            
    
            
            
                org.springframework.boot
                spring-boot-starter-test
                2.2.1.RELEASE
                test
            
    
            
            
                org.springframework.boot
                spring-boot-starter-data-redis
            
    
            
            
                org.apache.commons
                commons-pool2
                2.6.0
            
    
            
                com.alibaba
                fastjson
                1.2.24
            
    
        
        
            
                
                    org.springframework.boot
                    spring-boot-maven-plugin
                    
                        true
                    
                
            
        
    
    

    application.properties.xml

    #Redis服务器地址
    spring.redis.host=192.168.1.2
    #Redis服务器连接端口
    spring.redis.port=6379
    #Redis数据库索引(默认为0)
    spring.redis.database=0
    #连接超时时间(毫秒)
    spring.redis.timeout=1800000
    #连接池最大连接数(使用负值表示没有限制)
    spring.redis.lettuce.pool.max-active=20
    #最大阻塞等待时间(负数表示没限制)
    spring.redis.lettuce.pool.max-wait=-1
    #连接池中的最大空闲连接
    spring.redis.lettuce.pool.max-idle=5
    #连接池中的最小空闲连接
    spring.redis.lettuce.pool.min-idle=0
    # 关闭超时时间
    #pring.redis.lettuce.shutdown-timeout=100
    #配置spring启动端口号
    server.port=8080

    前端界面

    seckillpage.html

    
    
    
        
        redis秒杀
    
    
    
    
    
    
    
        

    商品1元秒杀

             -1"/>               " v-on:click="next" v-show="this.index<2"/>
        

    相关配置类

    Redis配置类

    RedisConfig.java

    package com.springboot_redis_seckill.config;
    
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.cache.CacheManager;
    import org.springframework.cache.annotation.CachingConfigurerSupport;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.cache.RedisCacheConfiguration;
    import org.springframework.data.redis.cache.RedisCacheManager;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.RedisSerializationContext;
    import org.springframework.data.redis.serializer.RedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    import java.time.Duration;
    
    /**
     * @author WuL2
     * @create 2021-05-27 14:26
     * @desc
     **/
    @EnableCaching
    @Configuration
    public class RedisConfig extends CachingConfigurerSupport {
    
        @Bean
        public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
            RedisTemplate template = new RedisTemplate<>();
            RedisSerializer redisSerializer = new StringRedisSerializer();
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(om);
            template.setConnectionFactory(factory);
            template.setKeySerializer(redisSerializer); //key序列化方式
            template.setValueSerializer(jackson2JsonRedisSerializer); //value序列化
            template.setHashValueSerializer(jackson2JsonRedisSerializer); //value hashmap序列化
            return template;
        }
    
        @Bean(name = "cacheManager")
        public CacheManager cacheManager(RedisConnectionFactory factory) {
            RedisSerializer redisSerializer = new StringRedisSerializer();
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
            //解决查询缓存转换异常的问题
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(om);
            // 配置序列化(解决乱码的问题),过期时间600秒
            RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofSeconds(600))
                    .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                    .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                    .disableCachingNullValues();
            RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                    .cacheDefaults(config)
                    .build();
            return cacheManager;
        }
    }

    配置Vue获取后端接口数据时出现的跨域请求问题。

    CorsConfig.java

    package com.springboot_redis_seckill.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.cors.CorsConfiguration;
    import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
    import org.springframework.web.filter.CorsFilter;
    
    
    /**
     * @author: wu linchun
     * @time: 2021/5/28 22:22
     * @description: 解决跨域问题(接口是http,而axios一般请求的是https。从https到http是跨域,因此要配置跨域请求)
     */
    
    @Configuration
    public class CorsConfig {
        private CorsConfiguration buildConfig() {
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            corsConfiguration.addAllowedOrigin("*"); //允许任何域名
            corsConfiguration.addAllowedHeader("*"); //允许任何头
            corsConfiguration.addAllowedMethod("*"); //允许任何方法
            return corsConfiguration;
        }
    
        @Bean
        public CorsFilter corsFilter() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", buildConfig()); //注册
            return new CorsFilter(source);
        }
    
    }

    服务层

    SecKillService.java

    package com.springboot_redis_seckill.service;
    
    public interface SecKillService {
        public boolean doSecKill(String uid,String productId);
    }

    SecKillServiceImpl.java

    package com.springboot_redis_seckill.service.impl;
    
    import com.springboot_redis_seckill.service.SecKillService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Service;
    
    /**
     * @author WuL2
     * @create 2021-05-27 14:53
     * @desc
     **/
    @Service
    public class SecKillServiceImpl implements SecKillService {
        @Autowired
        @Qualifier("redisTemplate")
        private RedisTemplate redisTemplate;
    
        @Override
        public synchronized boolean doSecKill(String uid, String productId) {
            //1、uid和productId非空判断
            if (uid == null || productId == null) {
                return false;
            }
    
            //2、拼接key
            String kcKey = "sk:" + productId + ":qt";   //库存
            String userKey = "sk:" + productId + ":user";  //秒杀成功的用户
    
            //3、获取库存
            String kc = String.valueOf(redisTemplate.opsForValue().get(kcKey)) ;
            if (kc == null) {
                System.out.println("秒杀还没有开始,请等待");
                return false;
            }
    
            //4、判断用户是否已经秒杀成功过了
            if (redisTemplate.opsForSet().isMember(userKey, uid)) {
                System.out.println("已秒杀成功,不能重复秒杀");
                return false;
            }
            //5、如果库存数量小于1,秒杀结束
            if (Integer.parseInt(kc) <=0) {
                System.out.println("秒杀结束");
                return false;
            }
    
            //6、秒杀过程
            redisTemplate.opsForValue().decrement(kcKey);  //库存数量减1
            redisTemplate.opsForSet().add(userKey, uid);
            System.out.println("秒杀成功。。。");
            return true;
        }
    }

    控制层

    package com.springboot_redis_seckill.controller;
    
    import com.alibaba.fastjson.JSONObject;
    import com.springboot_redis_seckill.service.SecKillService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Random;
    
    /**
     * @author WuL2
     * @create 2021-05-27 14:28
     * @desc
     **/
    @Controller
    @RequestMapping("/index")
    public class MyController {
        @Autowired
        @Qualifier("secKillServiceImpl")
        private SecKillService secKillService;
    
        @RequestMapping(value = {"/seckillpage"}, method = RequestMethod.GET)
        public String seckillpage() {
            return "/html/seckillpage.html";
        }
    
    
        @RequestMapping(value = {"/doSeckill"}, method = RequestMethod.POST)
        @ResponseBody  //自动返回json格式的数据
        public Object doSeckill(HttpServletRequest request, HttpServletResponse response) {
            System.out.println("doSeckill");
            String productId = request.getParameter("productId");  
            String index = request.getParameter("index");
            System.out.println(productId+index);  //拼接成为商品ID
            int id = new Random().nextInt(50000);  //使用随机数生成用户ID
            String uid = String.valueOf(id) + " ";
            boolean flag = secKillService.doSecKill(uid, productId+index);
            System.out.println(flag);
            return flag;
        }
    }

    启动类

    RunApplication.java

    package com.springboot_redis_seckill;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    /**
     * @author WuL2
     * @create 2021-05-27 14:32
     * @desc
     **/
    @SpringBootApplication
    public class RunApplication {
        public static void main(String[] args) {
            SpringApplication.run(RunApplication.class, args);
        }
    }

    3、启动步骤

    因为一共有三件商品要秒杀,所以在redis里面设置三个商品的库存数量。这里数量都设置为10。

    127.0.0.1:6379> set sk:012340:qt 10
    OK
    127.0.0.1:6379> set sk:012341:qt 10
    OK
    127.0.0.1:6379> set sk:012342:qt 10
    OK

    要确保redis能够被访问,要确保关闭linux的防火墙,以及关闭redis的保护模式。

    vim redis.conf   --打开redis配置
     
    service iptables stop   --关闭防火墙
     
     
    //关闭redis保护模式
    redis-cli    --进入redis客户端
    config set protected-mode "no"   --配置里面关闭redis保护模式(只是进入redis.conf把protected-mode变为no是不行的,还要加一句config set protected-mode "no"

    启动springboot项目

    怎么使用Springboot+redis+Vue实现秒杀系统

    怎么使用Springboot+redis+Vue实现秒杀系统

    秒杀成功后,该商品在redis中的数量就减1。

    怎么使用Springboot+redis+Vue实现秒杀系统

    当数量减为0时,则提示“抢光了”。

    怎么使用Springboot+redis+Vue实现秒杀系统

    怎么使用Springboot+redis+Vue实现秒杀系统

    4、使用ab进行并发测试

    如果是centOS 6版本的linux都是默认按照了ab工具的。

    如果没有安装ab工具,可在linux终端用命令联网下载安装。

    yum install httpd-tools

    安装完成后,就可以使用ab工具进行并发测试了。

    在linux终端输入如下命令:

    ab -n 2000  -c 200 -p '/root/Desktop/post.txt' -T 'application/x-www-form-urlencoded' 'http://192.168.1.6:8080/index/doSeckill/'

    怎么使用Springboot+redis+Vue实现秒杀系统

    012341这个商品库存变为0了

    怎么使用Springboot+redis+Vue实现秒杀系统

    5、线程安全

    为了防止出现“超买”的现象,需要让操作redis的方法是线程安全的(即在方法上加上一个“悲观锁”synchronized)。

    怎么使用Springboot+redis+Vue实现秒杀系统

    如果不加synchronized就会出现“超买”现象,即redis库存会出现负数

    怎么使用Springboot+redis+Vue实现秒杀系统

    怎么使用Springboot+redis+Vue实现秒杀系统

    之所以产生这种现象是由于并发导致多个用户同时调用了doSecKill()方法,多个用户同时修改了redis中的sk:012342:qt的值,但暂时都没有提交存入到redis中去。等到后来一起提交,导致了sk:012342:qt的值被修改了多次,因此会出现负数。

    因此在doSecKill()方法加上悲观锁,用户调用该方法就对该方法加锁,修改了sk:012342:qt的值后并提交存入redis中之后,才会释放锁。其他用户才能得到锁并操作该方法。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 VUE
    上一篇: java如何捕获InterruptedException错误
    下一篇: redis原子操作实例分析
    相关文章 更多
    vue上传文件格式怎么设置及要求说明
    vue上传文件格式怎么设置及要求说明

    学习如何在Vue项目中设置文件上传格式限制。本文介绍使用HTML accept属性进行基础过滤,以及结合JavaScript进行严格后缀名校验的方法,确保只允许指定类型的文件被上传。

    vue创建项目很慢怎么解决及常见原因排查教程
    vue创建项目很慢怎么解决及常见原因排查教程

    分析Vue项目创建缓慢的常见原因,包括网络延迟和依赖下载问题,提供切换镜像源、更换包管理器及使用Vite等具体优化方案,提升开发环境搭建效率。

    vue下载文件怎么做到点上就有反应在浏览器显示进度条
    vue下载文件怎么做到点上就有反应在浏览器显示进度条

    详解如何在Vue项目中利用Axios的onDownloadProgress回调捕获下载进度,并结合UI组件实时渲染进度条,同时分析Blob对象处理大文件时的内存限制与替代方案。

    uniapp网络请求拦截怎么设置方法详细教程
    uniapp网络请求拦截怎么设置方法详细教程

    学习如何在UniApp项目中设置网络请求拦截器,实现统一的Token管理、请求参数处理和响应错误捕获,优化前端开发体验。

    Vue页面空白的排查方法及解决办法
    Vue页面空白的排查方法及解决办法

    遇到Vue项目页面空白不要慌,本文通过路由匹配、组件生命周期、异步数据加载及权限控制四个真实场景,详解排查步骤与解决办法,助你快速恢复页面显示。

    php72w redis,docker php7安装php-redis
    php72w redis,docker php7安装php-redis

    在Docker环境下为PHP安装Redis扩展:手动编译需下载源码、安装phpize、配置编译并安装,生成redis.so并在php.d目录新建redis.ini加载,重启PHP-FPM;也可直接yum安装php72w-pecl-redis,免手动编译。

    php 如何配置 redis,php 如何设置redis
    php 如何配置 redis,php 如何设置redis

    配置PHP的Redis扩展:先安装Redis服务,从GitHub下载phpredis源码,用phpize编译安装,修改php.ini添加extension=redis.so,重启php-fpm或Apache,通过phpinfo验证并连接Redis。

    c++如何将结构体序列化为Redis兼容的RESP协议格式【深度】
    c++如何将结构体序列化为Redis兼容的RESP协议格式【深度】

    C++结构体无法直接序列化为RESP协议,需手动将字段映射为*N数组嵌套$lenbulkstring形式。整数需转换为字符串并加:前缀,空字符串用$0\r\n,null用$-1\r\n。长度计算需精确到字节数,特别注意二进制安全,同时确保字段顺序与结构体定义一致。

    如何在Golang架构中部署Redict作为高能数据临时存储中转站
    如何在Golang架构中部署Redict作为高能数据临时存储中转站

    Redis作为跨服务临时状态枢纽,需按消息队列、缓存和原子状态三重角色设计。选型用List实现任务分发及延迟重试,Stream用于事件广播与位点回溯。go-redis/v8需配置MinIdleConns、MaxRetries及超时。数据写入应JSON序列化并带type标签、设合理TTL、将关键字段提至顶层。消费通过原子GET+DEL或processedkey

    TP8.0 高并发下库存超卖?Redis 原子递减结合数据库乐观锁控制
    TP8.0 高并发下库存超卖?Redis 原子递减结合数据库乐观锁控制

    在高并发秒杀场景下,利用Redis的减库存原子操作预扣减库存拦截超卖请求,再通过数据库乐观锁(版本号与库存校验)确保最终一致性,异常时回滚Redis库存并借助Lua脚本保证原子性,从而有效防止库存超卖。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。

    即将离开本站
    您即将前往第三方网站,请确认是否继续?