秒杀系统设计

一、秒杀商品上架

一般是后台指定一个定时任务,上架秒杀商品
在这里插入图片描述
假如是集群部署的情况,就会出现分布式问题,可能会存在商品重复上架问题
解决方案也很简单,加一个分布式锁
在这里插入图片描述
商品上架流程图:
在这里插入图片描述

二、秒杀系统需要考虑的问题

在这里插入图片描述
在这里插入图片描述
1:抽取一个秒杀服务,独立部署,集群部署
2:采用动态随机码,加密处理
3:信号量控制-原子性
4:nginx动静分离
5:识别恶意攻击
6:使用各种手段,使得用户流程错峰
7:限流降级等
8:队列削峰,添加一个队列接受秒杀成功的请求

三、秒杀流程

1、加入购物车秒杀流程:
在这里插入图片描述
2、立即抢购秒杀流程:
在这里插入图片描述
秒杀接口实现:

public String kill(String killId, String key, Integer num) {

        MemberRespVo memberRespVo = LoginUserInterceptor.loginUser.get();

        // 1、获取当前秒杀商品的详细信息
        BoundHashOperations<String, String, String> ops = redisTemplate.boundHashOps(SKUKILL_CACHE_PREFIX);
        String s = ops.get(killId);
        if(!StringUtils.isEmpty(s)) {
            SeckillSkuRedisTo redisTo = JSON.parseObject(s, SeckillSkuRedisTo.class);
            // 校验合法性
            Long startTime = redisTo.getStartTime();
            Long endTime = redisTo.getEndTime();

            long ttl = endTime - startTime;
            // 校验时间的合法性
            if(startTime <= new Date().getTime() && new Date().getTime() <= endTime ) {
                // 校验随机码和商品id
                String randomCode = redisTo.getRandomCode();
                String skuId = redisTo.getPromotionSessionId() + "_" + redisTo.getSkuId();
                if(randomCode.equals(key) && killId.equals(skuId)) {
                    // 3、验证购物数量是否合法
                    if(num <= redisTo.getSeckillLimit()) {
                        // 4、验证这个人是否已经购买过。幂等性;如果只有秒杀成功,就去占位
                        String redisKey = memberRespVo.getId() + "_" + skuId;
                        // 自动过期
                        Boolean absent = redisTemplate.opsForValue().setIfAbsent(redisKey, num.toString(), ttl, TimeUnit.MILLISECONDS);
                        if(absent) {
                            // 占位成功,没买过
                            RSemaphore semaphore = redissonClient.getSemaphore(SKU_STOCK_SEMAPHORE + randomCode);
                            boolean tryAcquire = semaphore.tryAcquire(num);
                            if(tryAcquire) {
                                // 秒杀成功
                                // 快速下单 发送MQ消息
                                String timeId = IdWorker.getTimeId();
                                SeckillOrderTo seckillOrderTo = new SeckillOrderTo();
                                seckillOrderTo.setOrderSn(timeId);
                                seckillOrderTo.setMemberId(memberRespVo.getId());
                                seckillOrderTo.setNum(num);
                                seckillOrderTo.setPromotionSessionId(redisTo.getPromotionSessionId());
                                seckillOrderTo.setSeckillPrice(redisTo.getSeckillPrice());
                                seckillOrderTo.setSkuId(redisTo.getSkuId());
                                rabbitTemplate.convertAndSend("order-event-exchange","order.seckill.order",seckillOrderTo);
                                return timeId;
                            }
                        }
                    }
                }
            }
        }


        return null;
    }

四、秒杀成功创建订单流程

在这里插入图片描述
监听削峰队列,创建订单

@RabbitListener(queues = "order.seckill.order.queue")
@Component
public class OrderSeckillListener {

    @RabbitHandler
    public void listener(SeckillOrderTo seckillOrder, Channel channel, Message message) throws IOException {
        try {
            log.info("准备创建秒杀单的详细信息...");
            // 创建订单
			// 业务逻辑
			
			// ack确认
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值