栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

秒杀系统设计

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

秒杀系统设计

秒杀系统设计
  • 一、秒杀商品上架
  • 二、秒杀系统需要考虑的问题
  • 三、秒杀流程
  • 四、秒杀成功创建订单流程

一、秒杀商品上架

一般是后台指定一个定时任务,上架秒杀商品

假如是集群部署的情况,就会出现分布式问题,可能会存在商品重复上架问题
解决方案也很简单,加一个分布式锁

商品上架流程图:

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



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 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);
        }
    }

}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/851111.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号