电商 - 秒杀商品之高并发(3) - Redis存储,数据库更新,MQ消峰,延迟请求

使用Redis存储,数据库及时更新,MQ消峰请求,延迟请求时间,前端做拼图,限流,限表单重复提交,利用原子性,悲观锁,事务,保持商品一致性,不超卖!

代码还在研发中…等有空就发布出来,实现起来不难,还有性能方面,可以从数据库方面着手,数据库利用好了,性能可以提高几倍!好了,暂时聊到这里,我要去学习liunx去了。

中午没有午休,写了一个简单的例子,这个例子如果要用到正式环境,可能需要做一些改动,我会在代码上面进行备注。

数据库图: 20个商品。
在这里插入图片描述

Redis图: 20个商品。
在这里插入图片描述

Redis图: 100个用户请求,现在是0,只能进来100个请求。
在这里插入图片描述
JMeter测试图: 10万个请求,5秒跑完。

在这里插入图片描述
代码: 代码我只突出impl层。

/**
     * Redis存储,数据库更新,用MQ更新数据库
     * @param param
     */
    @Override
    public void orderAdd3(OrderParam param) {
        try {
            //10万个用户请求
            long count = RedisUtil.incr( "quantity");
            System.out.println("进来的请求是:" + count);

            //只要100个用户,其他的用户全部是返回抢购完成
            if(100 <= count){
                System.out.println("已经抢购完成");
                return; //自定义返回异常
            }else {
                Integer i = Integer.valueOf(RedisUtil.get("commdity"));
                System.out.println("剩下商品数量是: " + i);
                if(i <=0) {
                    System.out.println("库存不足,停止售卖");
                    return; //自定义返回异常
                }
                //使用decrBy原子性,保证商品不被超卖,需要考虑,如果用户买了10个商品,但是商品库存没有10个,那么需要把扣的商品进行补回去!
                RedisUtil.decrBy("commdity",  param.getQuantity());

                //放入MQ中,异步减库存
                SendCaptcha sendCaptcha = new SendCaptcha();
                BeanUtils.copyProperties(param,sendCaptcha);
                sendCaptcha.setCount((int) count);
                String jsonString = JSONObject.toJSONString(sendCaptcha);
                rabbitTemplate.convertAndSend(TZGMQConfig.TZG_QUEUE_INFORM,jsonString);
            }
        }catch (Exception e){
            System.out.println("出现异常");
        }
    }

MQ消费者进行消峰:

 //监听sms队列
    @RabbitListener(queues = {TZGMQConfig.TZG_QUEUE_INFORM})
    public void receive_sms(String msg, String source){
        try {
            SendCaptcha sendCaptcha = JSONObject.parseObject(source, SendCaptcha.class);
            System.out.println("获取到的sms消息==" + sendCaptcha);
            commodityMapper.updateOrder(sendCaptcha.getCommodityId(),sendCaptcha.getQuantity());
            System.out.println("更新数据库");
        }catch (Exception e){
            log.error("RabbitMQ consumer throws Exception test");
            e.printStackTrace();
        }
    }

SQL:

 update tar_commodity set quantity = (quantity - #{quantity}) where id = #{commodityId} and (quantity - #{quantity}) >= 0

IDEA控制台打印效果图:

在这里插入图片描述
数据库效果图:
在这里插入图片描述
Redis效果图:商品
在这里插入图片描述
Redis效果图:请求
在这里插入图片描述
下篇会写多线程,在服务器加悲观锁,与原子性控制,择其善者而从之,其不善者而改之。

发布了72 篇原创文章 · 获赞 16 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_40206199/article/details/103271244