彻夜怒肝!SpringBoot+Reids高并发秒杀系统源码!

彻夜怒肝!SpringBoot+Reids高并发秒杀系统源码!

在电商业务中,秒杀属于技术挑战最大的业务,只有经验够丰富、底子够稳的程序员,才能够hold住从搭建、上线到调优全链路。双十一就是一个经典的秒杀案例,动辄数十万笔的交易请求,对于我们来说,核心的两个问题:1-高并发读取与写入(涉及到集群,负载,读写分离,分库分表等操作)2-性能优化(玩转降级、限流、拒绝服务这三件法宝)程序员们应该都知道这样一句话:在工作中如果知道问题出现在哪里、是怎么发生的,问题就解决了一半。而从“不懂”到“知道”,中间不是鸿沟天堑,往往只差一次亲身经历。此外,应对工作中可能出现的突发情况,你也能知道从哪些环节来设计兜底方案。比如核心的抢单线程池设计与实现:public class AsyncConfiguration {

    @Bean(“doSomethingExecutor”)

    public Executor doSomethingExecutor() {

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        // 核心线程数:线程池创建时候初始化的线程数

        executor.setCorePoolSize(10);

        // 最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程

        executor.setMaxPoolSize(20);

        // 缓冲队列:用来缓冲执行任务的队列

        executor.setQueueCapacity(500);

        // 允许线程的空闲时间60秒:当超过了核心线程之外的线程在空闲时间到达之后会被销毁

        executor.setKeepAliveSeconds(60);

        // 线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池

        executor.setThreadNamePrefix(“create-seckill-order”);

        // 缓冲队列满了之后的拒绝策略:由调用线程处理(一般是主线程)

        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());

        executor.initialize();

        return executor;

    }

}

再比如复杂的多线程异步操作实现:

    /*****

     * 异步操作方法

     *      run

     * 注解:@Async

     */

    @Async

    public void createOrder(){

        try {

            log.info(“—-准备@Async执行—-“);

            //Thread.sleep(10000);

//            redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<SeckillStatus>(SeckillStatus.class));

            SeckillStatus seckillStauts = (SeckillStatus) redisTemplate.boundListOps(“SeckillOrderQueue”).rightPop();

            //用户抢单数据

            String username=seckillStauts.getUsername();

            String time=seckillStauts.getTime();

            Long id=seckillStauts.getGoodsId();

            //获取队列中的商品id,使用Redis的队列来解决超卖的问题

//            redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Long[]>(Long[].class));

            Object sid = redisTemplate.boundListOps(“SeckillGoodsCountList_” + id).rightPop();

            //售罄

            if(sid==null){

                //清理排队信息

                clearQueue(seckillStauts);

                return;

            }

            //查询商品详情

//            redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<SeckillGoods>(SeckillGoods.class));

            SeckillGoods goods = (SeckillGoods) redisTemplate.boundHashOps(“SeckillGoods_”+time).get(id);

            //Thread.sleep(10000);

            log.info(username+”:”+Thread.currentThread().getId()+”—-查询到 的商品库存:”+goods.getStockCount());

            if(goods!=null && goods.getStockCount()>0){

                //创建订单

                SeckillOrder seckillOrder = new SeckillOrder();

                seckillOrder.setId(idWorker.nextId());

                seckillOrder.setSeckillId(id);

                seckillOrder.setMoney(goods.getCostPrice());

                seckillOrder.setUserId(username);

                seckillOrder.setSellerId(goods.getSellerId());

                seckillOrder.setCreateTime(new Date());

                seckillOrder.setStatus(“0”);

                //TODO 支付成功后再入库

                seckillOrderMapper.insertSelective(seckillOrder);

                redisTemplate.boundHashOps(“SeckillOrder”).put(username,seckillOrder);

                //库存削减【关键的判断因素,需要从Redis中进行判断,否则两个库存同时进入这儿的逻辑,真是库存都是1,实际是0;使用自增来解决】

                //Integer stockCount = goods.getStockCount()-1;

                //Long surplusCount = stockCount.longValue();

               Long surplusCount = redisTemplate.boundHashOps(“SeckillGoodsCount”).increment(goods.getId(), -1);

                log.info(“库存消减后剩余:”+surplusCount);

                goods.setStockCount(surplusCount.intValue());

                //商品库存=0->将数据同步到MySQL,并清理Redis缓存

                if(surplusCount<=0){

                    seckillGoodsMapper.updateByPrimaryKeySelective(goods);

                    //清理Redis缓存

                    redisTemplate.boundHashOps(“SeckillGoods_”+time).delete(id);

                }else{

                    //将数据同步到Redis

                    redisTemplate.boundHashOps(“SeckillGoods_”+time).put(id,goods);

                }

                log.info(“—-准备更新seckillStauts—-“);

                //变更抢单状态

                seckillStauts.setOrderId(seckillOrder.getId());

                seckillStauts.setMoney(seckillOrder.getMoney().floatValue());

                seckillStauts.setStatus(2); //抢单成功,待支付

                redisTemplate.boundHashOps(“UserQueueStatus”).put(username,seckillStauts);

                log.info(“—-准备更新seckillStauts完毕—-“);

                //发送延迟消息

                //延时30m发送,级别是16

                SendResult result=rocketMQTemplate.syncSend(“seckill_order:delay”, MessageBuilder.withPayload(seckillStauts).build(),2000,16);

                System.out.println(result.toString());

            }

            log.info(“—-正在执行—-“);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

    /***

     * 清理用户排队信息

     * @param seckillStauts

     */

    private void  clearQueue(SeckillStatus seckillStauts) {

        //清理重复排队标识

        redisTemplate.boundHashOps(“UserQueueCount”).delete(seckillStauts.getUsername());

        //清理排队存储信息

        redisTemplate.boundHashOps(“UserQueueStatus”).delete(seckillStauts.getUsername());

    }

}

这都是我在实战中总结的经验。可以说,不论是跳槽到更好的工作岗位,还是想提升自己的代码质量,都离不开高并发环境下真实项目的锤炼,初级开发想要增加自己对复杂并发系统的掌控力,一套模拟大厂真实并发量的秒杀系统是最好的实训项目当然,从0设计一个高性能秒杀系统并非易事,其实包含许多复杂的问题。下面这个秒杀系统架构【精准千人千面闯关实战】,前转转平台架构部负责人东叔精心设计,截至目前已有8w+人报名,干货多到值得重复听2遍、3遍,已经帮助过无数后端开发突破成长瓶颈,强化自身基础。5月23日~5月25日闯关实战10+高开核心模块,原价499前50位报名仅需 ¥1免费赠送高薪工程师(P6~P9)能力评估一次

👆长按扫码报名👆等于说把这套秒杀系统从搭建到上线再到调优,都一一讲给你听,相信你看完、学完之后,也能自己实现一个完成度较高的秒杀系统。为什么推荐你加入这次实战?通过闯关实战,你将完整洞悉大厂微服务架构和高并发系统的设计流程,对基于 Redis 分布式系统核心组件RPC、注册中心、消息队列、配置中心等组件了如指掌,掌握分布式系统模块设计、核心难点问题的解决,以及分布式系统必备核心组件的使用。

在闯关实战开始前,加赠理论单元👇

在闯关实战直播中,你将收获👇第一天实战内容秒杀性能调优篇基于电商系统真实案例,详解 Redis 缓存在电商系统中到底有什么用、又该怎么用。第二天是项目实战应用篇。详尽解读 Redis 在统计、秒杀和广播项目中的实战应用,涉及调优、事故处理、热点 key 优化等核心技术点,同时提供项目源码+完整干货资料。第三天是思维模型进阶篇在最后一天学习中,名师将从市场环境与技术趋势出发,通过分享个人经验拉升你的认知,帮助你用 CTO 的视角审视技术与架构的哲学关系。详细内容都在目录里,可以完整看看:

01

什么是“精准千人千面闯关实战”?

(向上滑动查看)

02

报名享双重勤学福利

  ▶勤学福利1报名训练营即可免费领取高薪工程师(P6~P9)能力模型评估一次,帮助你针对薄弱技术维度精准查漏补缺。

▶勤学福利2:报名课程学完后,可直接内推到字节、阿里、 腾讯、百度等大厂,相当于为企业定向招聘,为每一位学员私人定制内推就业服务。

奈学和猎聘已达成深度合作

03

累计8w+人学过,好评如潮!

截至目前已有8w+人订阅学习,这么多期以来几乎从未收到过负面评价,清一水的好评:内容很干、很实用、给工作面试带来不少启发。

干货

干货多到值得重复听2、3遍

全程干货,不注水

实用

收获不止于课程内容

帮助过无数后端开发突破成长瓶颈,强化自身基础

机遇

面试Offer拿到手软

应对跳槽,轻松拿下offer

04

金牌教研团打造一站式学习服务

课程期间,奈学的教研团队还提供全程答疑服务奈学金牌教研团,平均从业年限10年以上,具备大厂实战经验,对技术深度钻研,对教学精益求精,让我们有理由相信,这套课程绝对物超所值。本期主讲大咖:

报名即享“8大定制化”闭环服务。学习过程中通过定制化的学前测评、课后作业,以及源码学习资料、完整课件内容,全方位提升学习效果。

在这次真实项目实训营中,你将获取和提升以下能力:

“1+1+1”闯关学习新模式,理论单元 + 案例剖析 + 场景实战

从 Redis 底层架构入手,深入浅出“Redis为什么这么快?”;

3 大实战项目,详解 Redis 秒杀系统、统计系统、广播系统;

重点解决面试必考之 Redis 主从复制、集群原理难题;

3 天重磅实战内容升级,免费附赠项目源码 + 课件。

训练营将基于一线秒杀、广播等企业级生产环境项目,帮助你深入理解 Redis 缓存机制及作为 MQ 的优势与亮点,彻底掌握秒杀系统的主从复制集群、持久化等核心技术点。

推荐给所有初、中级 Java 开发工程师,真的很值得一看。

点击「阅读原文」抢限时钜惠仅需 ¥1 拿下口碑好课

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Proudly powered by WordPress | Theme: HoneyWaves by SpiceThemes