大型PHP電商網站商品秒殺功能實現思路分析

my38778570發表於2022-05-12
  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 協議》,轉載必須註明作者和本文連結

相關文章