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; }
待续。。。。。。
PS: