秒杀系统思路

只提供一种思路,可用作面试。需要自己结合代码去实践

商品秒杀

秒杀服务一般单独部署

秒杀商品存入缓存。利用redis原子性操作防止超卖以及高并发。

秒杀异步下单实现
  • 将秒杀商品放入对应时间段的redis中。进行预处理。–防止超卖原子性操作
  • 异步下单:预扣减缓存中的库存再异步(mq)扣除mysql数据
  • 保证生产者发送的消息mq中不丢失:
  1. mq开启交换机、队列、消息的持久化(将mq的数据写入磁盘防止宕机)。
  2. 开启mq数据保护机制的confirm异步机制进行异步的消息确认(防止写入失败情况出现。生产者收到失败则继续发,成功则删除相应备份消息数据)。
  3. 生产者将发送的消息做一个备份(存在缓存或者mysql中即可),防止发送失败后重新发送。
  • 保证消费消费消息不丢失:消费者改为手动应答模式。在处理完成业务逻辑(修改mysql数据)后根据执行结果进行手动给mq进行应答。

  • 流量削峰:控制消费者接受消息总数(消费者预抓取总数控制)。

    防止雪崩:例如消费者最多接受1w条,1s时mq给了1w个,2s时mq又给了1w个消息,消费者可能为处理完上1w个数据就会导致手动确认为失败,这时mq就会继续将未成功的消息发送,会导致消费者超出处理能力而系统宕机。

防止恶意刷单

根据用户名+id为key存储到redis,值为每次+1操作>1则判定为恶意刷单,返回即可。

/**
     * 防止重复提交
     *      根据用户名和商品id为key往redis中存储一个值,相同则值+1*/
    private String preventRepeatCommit(String username,Long id) {
        String redisKey = "seckill_user_" + username+"_id_"+id;
        long count = redisTemplate.opsForValue().increment(redisKey, 1);
        if (count == 1){
            //设置有效期五分钟
            redisTemplate.expire(redisKey, 5, TimeUnit.MINUTES);
            return "success";
        }
        if (count>1){
            return "fail";
        }
        return "fail";

    }
防止相同商品重复秒杀

根据订单中用户名和商品id确定是否购买过该商品

下单接口隐藏

在前端请求中定义一个生成随机串的请求,作为包裹,在请求响应中请求真正的下单接口,对随机串进行校验一致则执行不一致则返回。

//秒杀下单
				add:function(id){
					app.msg ='正在下单';
					//获取随机数
					axios.get("/api/wseckillorder/getToken").then(function (response) {
						var random=response.data;
						axios.get("/api/wseckillorder/add?time="+app.dateMenus[0]+"&id="+id+"&random="+random).then(function (response) {
							if (response.data.flag){
								app.msg='抢单成功,即将进入支付!';
							}else{
								app.msg='抢单失败';
							}
						})
					})
				}
 @RequestMapping("/add")
    @ResponseBody
    public Result add(String time, Long id) {
        String coo = this.readCookie();
        //下单接口的隐藏。校验密文有效
        String randomcode = (String) redisTemplate.boundValueOps("randomcode_"+coo).get();
        if (!randomcode.equals(randomcode)){
            return new Result(false, StatusCode.ERROR,"无效访问");
        }
        Result result = secKillOrderFeign.add("2021092416", id);
        return result;
    }

    /**
     * 接口加密
     * 生成随机数存入redis,10秒有效期
     */
    @GetMapping("/getToken")
    @ResponseBody
    public String getToken() {
        String randomString = RandomUtil.getRandomString();
        //将cookie中的jti的值作为redis的key
        String cookieValue = this.readCookie();
        redisTemplate.boundValueOps("randomcode_" + cookieValue).set(randomString, 10, TimeUnit.SECONDS);
        return randomString;
    }

    //读取cookie
    private String readCookie() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String cookieValue = CookieUtil.readCookie(request, "uid").get("uid");
        return cookieValue;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值