关于一个秒杀或团抢活动的面试提问思考

RT: 

一个秒杀系统,当前物品有100个,活动上线有2000W用户参与,怎么设计这个架构。实现秒杀?

 

思考:

恶意刷单、页面静态化、CDN、缓存、域名、图片服务器、分布式、队列、高并发、流量削峰、RPC。

订单库存有限、尽量快速反馈用户结果。

 

前端:

1.商品详情下单页静态化,静态文件资源JS、CSS、IMG资源文件独立域名,资源文件CDN化或者自建suqid缓存服务器。 

2.下单按钮可做防重复提交设置。用户点击下单按钮后,操作变灰。或借助cookie或者前端框架如avalon保存用户操作时间,js限制单位时间只能提交一次。

3.防止URL直接提交恶意刷单。设置下单url有效期、URL可变化或使用表单令牌限制等。

 

后端:

前端已经防止了一些重复或不必要的请求传递给后端服务器。这时还是难以避免高并发。并发过大,可能会导致流量暴增,应用挂掉。

1.秒杀系统独立域名独立部署,在高并发情况下就算服务宕机也不影响正常的下单系统。

2.使用消息队列、或内存栅栏抵挡大量高并发请求。可以使用MQ或基于内存的K-V缓存服务器如Redis。

 

方案一:使用MQ

用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面。

 

<?php

$product_total = 100;
$product_id = Request::instance()->getPost('product_id')
$uid = Session::instance()->getUser()->getUid();


if(!filterRequest($product_id,$uid) || !order($product_id,$product_total,$uid)){
    $this->redirectUrl('/error/404.html');
}

$this->redirectUrl('/success.html');


function filterRequest(){
    //判断用户是否有购买资格
    if(){
        return false;
    }
    
    //其他判断
}

function order($productId,$productTotal,$uid){
    //判断是否总数大于等于库存
    if($productTotal >= Redis::instance()->scard($productId)){
        return false;
    }
    
    //追加用户为可购买
    $ret = Redis::instance()->sadd($productId, $uid);
    //设置一天有效时间
    Redis::instance()->expire($productId,86400);
    
    return $ret;
}
View Code

 

 

待续。。。。。。

 

PS:

关于消息队列的使用

 

posted @ 2017-04-21 00:34  phpdragon  阅读(631)  评论(0编辑  收藏  举报