大型PHP电商网站商品秒杀功能实现思路分析

项目背景介绍

  1. 关键点
  • 高可用:双活
  • 高并发:负载均衡、安全过滤
  1. 设计思路
  • 静态页面:cdn、网址隐藏、页面压缩、缓存机制
  • 动态页面:排队、异步、资质抢购
  1. 其他建议
  • 百度的建议:opcode缓存、cdn、更大的服务器实例
  • 阿里的建议:云监控、云盾、ecs、oss、rds、cdn

秒杀项目架构分析

  1. 认清当前的环境、形式
  • 用户:超大量、正常/坏人
  • 地域:全国各地
  • 业务流程:[前台]商品展示、登记、[后台]数据接入、数据处理

Laravel

技术实现要点分析

商品展示层

页面状态
  • 商品展示:秒杀倒计时页面
  • 秒杀进行中:点击进入秒杀页面
  • 秒杀活动结束:提示活动已结束

Laravel

用户登记层

页面状态
  • 秒杀进行中:秒杀登记页面
  • 秒杀结束了:秒杀结束页面

Laravel

数据接入层

页面功能
  • 数据校验:完成对数据、用户验证
  • 存入nosql队列:去重复、排序数据
  • 检测商品最大数量:提示活动已结束

Laravel

数据处理层

页面功能
  • 数据持久化:转存nosql数据到mysql数据
  • 存入nosql队列:去重复、排序数据
  • 检测商品最大数量:提示活动已结束

代码实现分析

第一层:商品展示层

知识点

页面/服务器优化、CDN网络加速、隐藏跳转页面、状态切换

  1. 秒杀页脚本
  • miao.sh
    #!/usr/bin/env bash
    date >> /root/456.txt
    # 删除秒杀等待页面
    rm -rf '/var/www/html/index.html'
    # 复制秒杀页面到/var/www/html/index.html
    cp '/var/www/html/index_sale.html' '/var/www/html/index.html'
  1. 计划任务
    • crontab linux计划任务
# 目前每分钟执行一次,具体各自配置
*/1 * * * * root /bin/miao.sh
  1. 秒杀结束
  • set_file.phpindex_over.html覆盖/var/www/html/index.html
<?php
//第一步:删除文件
$file_path = 'index.html';
$f = file_exists($file_path) && unlink($file_path);

//第二步:生成自己需要的文件
$file_path = 'index.html';
$myfile =   fopen($file_path, "w");

//获取文件内容
$file_path = 'index_over.html';
$txt = file_get_contents($file_path);
fwrite($myfile, $txt);

第二层:用户登记层

知识点

格外增加:token加/解密、ajax跨域

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        var url = "./miaosha.php";
        $("#qianggou").click(function () {
            var myphone = $("#myphone").val();
            var mynumber = $("#mynumber").val();
            var data = {
                'phone': myphone,
                'number': mynumber,
            };
        });
        $.ajax({
            url: url,
            data: data,
            dataType: 'jsonp',
            jsonp: "callback",//传递给请求处理程序或页面的,用以获取jsonp回调函数名的参数名(默认为:callback)
            jsonpCallback: "success_jsonpCallback",//自定义的jsonp回调函数名称,默认为jquery自动生成的随机函数
            success: function (cc) {
                if (cc.msg = "ok") {
                    $.cookie('miao', 'ok')
                }
            },
            error: function () {
                $.cookie('miao', null)
            },
            timeout: 300
        });
        //检测是否秒杀了
        var miao =   $.cookie('miao')
        if (miao) {
            alert('你已秒杀');
        }
    </script>
</body>

</html>

第三层:数据接入层

知识点

数据校验、存入队列、商品数量检测

#miaosha.php
<?php

namespace miaosha;
//允许指定域名访问、防止跨域
header('Access-Control-Allow-Origin:http://xxxxx.cn');
$redis = new \Redis();
//获取$.ajax提交的数据
$value = ['phone' => 'xxxx', 'number' => '1'];
$value = serialize($value);

if (setValue($value) == "overflow") {
    //执行set_file.php秒杀结束
} else {
    $data = ['msg' => 'ok'];
}

//返回结果到前台
$callback = $_GET['callback'];
echo $callback . '(' . json_encode($data) . ')';

function setValue($value)
{
    $redis = new \Redis();
    //设置基数标志位
    if (!$redis->get('flat')) {
        $redis->set('flat', 1);
    }
    //检测溢出,最大100
    if ($redis->get('flat') > 100) {
        return 'overflow';
    }
    //插入非重复数据
    if ($redis->zAdd('miaoKey', $redis->get('flat'), $value)) {
        $redis->incr('flat');
    }
}

function getValue()
{
    $redis = new \Redis();
    return $redis->zRange('miaoKey', 0, -1);
}

第四层:数据处理层

知识点

数据持久化

#set_mysql.php
<?php
//转存信息,进入到mysql进行数据持久化
 $redis = new \Redis();
 $data = $redis->zRange('miaoKey', 0, -1);
//插入mysql....

抢购升级

加机器(简单粗暴),高峰过后会浪费

  1. 系统解耦(资源隔离,当前业务放在单独的集群上面)
  2. 限流和过载保护(根据后端承载能力,进行限流,防止全网挂掉,使用redis承载海量QPS)
  3. 高峰期做docker弹性扩缩容处理
  4. 做一套独立的秒杀系统(秒杀系统挂了,也不影响其他正常运行)
  5. 整个系统采用GO重新开发,极大提高了系统的性能(十台php可能才承载2万QPS,十台go能承载50万QPS)
  6. 降级预案
  7. 分析异常请求,设置黑白名单

秒杀接入层 1.长连接 2.ip黑名单 3.抢购开关(突发事件,需要关闭) 4.url校验 5.refer白名单 6.id黑名单

来源
大型PHP电商网站商品秒杀功能实现思路分析

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 3

setValue函数不能防止超卖

1年前 评论
my38778570 (楼主) 1年前

秒杀商品数量多少个?需要十台设备,这个系统有点大

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!