秒杀系统设计实现

青旅半醒 2022-04-18 02:29 420阅读 0赞

一、题目

这是一个秒杀系统,即大量用户抢有限的商品,先到先得
用户并发访问流量非常大,需要分布式的机器集群处理请求
系统实现使用Java

二、模块设计

1、用户请求分发模块:使用Nginx或Apache将用户的请求分发到不同的机器上。

2、用户请求预处理模块:判断商品是不是还有剩余来决定是不是要处理该请求。

3、用户请求处理模块:把通过预处理的请求封装成事务提交给数据库,并返回是否成功。

4、数据库接口模块:该模块是数据库的唯一接口,负责与数据库交互,提供RPC接口供查询是否秒杀结束、剩余数量等信息。

第一部分就不多说了,配置HTTP服务器即可,这里主要谈谈后面的模块。

用户请求预处理模块:

经过HTTP服务器的分发后,单个服务器的负载相对低了一些,但总量依然可能很大,如果后台商品已经被秒杀完毕,那么直接给后来的请求返回秒杀失败即可,不必再进一步发送事务了,示例代码可以如下所示:








  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
  1. package seckill;
     
    import org.apache.http.HttpRequest;
     
    /
    预处理阶段,把不必要的请求直接驳回,必要的请求添加到队列中进入下一阶段.
  2. /
    public class PreProcessor {
    // 商品是否还有剩余
    private static boolean reminds = true;
     
    private static void forbidden() {
    // Do something.
    }
     
    public static boolean checkReminds() {
    if (reminds) {
    // 远程检测是否还有剩余,该RPC接口应由数据库服务器提供,不必完全严格检查.
    if (!RPC.checkReminds()) {
    reminds = false;
    }
    }
    return reminds;
    }
     
    /

    每一个HTTP请求都要经过该预处理.
  3. /
    public static void preProcess(HttpRequest request) {
    if (checkReminds()) {
    // 一个并发的队列
    RequestQueue.queue.add(request);
    } else {
    // 如果已经没有商品了,则直接驳回请求即可.
    forbidden();
    }
    }
    }

并发队列的选择

Java的并发包提供了三个常用的并发队列实现,分别是:ConcurrentLinkedQueue 、 LinkedBlockingQueue 和 ArrayBlockingQueue。

ArrayBlockingQueue是初始容量固定的阻塞队列,我们可以用来作为数据库模块成功竞拍的队列,比如有10个商品,那么我们就设定一个10大小的数组队列。

ConcurrentLinkedQueue使用的是CAS原语无锁队列实现,是一个异步队列,入队的速度很快,出队进行了加锁,性能稍慢。

LinkedBlockingQueue也是阻塞的队列,入队和出队都用了加锁,当队空的时候线程会暂时阻塞。

由于我们的系统入队需求要远大于出队需求,一般不会出现队空的情况,所以我们可以选择ConcurrentLinkedQueue来作为我们的请求队列实现:








  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  1. package seckill;
     
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.ConcurrentLinkedQueue;
     
    import org.apache.http.HttpRequest;
     
    public class RequestQueue {
    public static ConcurrentLinkedQueue<HttpRequest> queue =
    new ConcurrentLinkedQueue<HttpRequest>();
    }

用户请求模块








  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
  1. package seckill;
     
    import org.apache.http.HttpRequest;
     
    public class Processor {
    /*
  2. 发送秒杀事务到数据库队列.
    */
    public static void kill(BidInfo info) {
    DB.bids.add(info);
    }
     
    public static void process() {
    BidInfo info = new BidInfo(RequestQueue.queue.poll());
    if (info != null) {
    kill(info);
    }
    }
    }
     
    class BidInfo {
    BidInfo(HttpRequest request) {
    // Do something.
    }
    }

数据库模块:

数据库主要是使用一个ArrayBlockingQueue来暂存有可能成功的用户请求。








  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
  1. package seckill;
     
    import java.util.concurrent.ArrayBlockingQueue;
     
    /*
  2. DB应该是数据库的唯一接口.
    */
    public class DB {
    public static int count = 10;
    public static ArrayBlockingQueue<BidInfo> bids = new ArrayBlockingQueue<BidInfo>(10);
     
    public static boolean checkReminds() {
    // TODO
    return true;
    }
     
    // 单线程操作
    public static void bid() {
    BidInfo info = bids.poll();
    while (count > 0) {
    // insert into table Bids values(item_id, user_id, bid_date, other)
    // select count(id) from Bids where item_id = ?
    // 如果数据库商品数量大约总数,则标志秒杀已完成,设置标志位reminds = false.
    info = bids.poll();
    }
    }
    }

三、结语

看起来大体这样应该就可以了,当然还有细节可以优化,比如数据库请求可以都做成异步的等等。

发表评论

表情:
评论列表 (有 0 条评论,420人围观)

还没有评论,来说两句吧...

相关阅读

    相关 系统设计思路

    一、限流与降级 客户端限流 按钮置灰 js控制每秒只能发送一个请求 站点层限流 1. Nginx限流 Nginx官方版本限制IP的连接和并发分别有两个模

    相关 设计一个系统-方案分析

    学习使用,老鸟飞过,欢迎交流 秒杀系统应该考虑哪些因素 高可用:秒杀系统最大的特点就是并发高,在极短的时间内, 瞬间用户量大。试想一下双11的时候可能会有几十万的用户去

    相关 系统设计实现

    一、题目 这是一个秒杀系统,即大量用户抢有限的商品,先到先得 用户并发访问流量非常大,需要分布式的机器集群处理请求 系统实现使用Java 二、模块设计 1、用户请

    相关 系统设计(一)

    秒杀系统的场景特点 秒杀时大量用户会在同一时间同时进行抢购,网站瞬时访问流量激增; 秒杀一般是访问请求量远远大于库存数量,只有少部分用户能够秒杀成功;