php秒殺系統架構設計實例

2020-02-18   瀏覽量:

  ① 對現有網站業務的沖擊,如果秒殺程序部署到現有的服務器上,可能導致整個網站癱瘓

  解決方法

  把秒殺活動部署到單獨的機子上,并且用單獨的域名

  ② 高并發,用戶在秒殺活動開始之前會不停的刷新頁面,如果用php腳本連接數據庫的方式,會對服務器的壓力較大

  解決方法

  使用靜態頁面,并且使用cdn緩存,解決帶寬壓力大等問題

  ③ 避免用戶直接通過下單連接下單

  解決方法

  帶個隨機參數,在秒殺開始之前才能得到

  ④ 控制搶購按鈕,頁面設計為靜態頁面并且使用了cdn緩存,如何點亮搶購按鈕

  解決方法

  js文件后面帶個隨機版本號,這樣不會被cdn緩存,直接到達服務器,來控制按鈕點亮,這個js文件要小,不然會對服務器帶來帶寬的壓力

  ⑤ 搶購程序設計,如果直接使用數據庫事務,數據庫壓力太大

  解決方法

  使用redis或memcache等內存緩存,速度快還能解決超賣等問題

  搶購靜態頁面代碼

搶購靜態頁面代碼


  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title>秒殺!</title>
  6. <link rel="stylesheet" href="/public/css/level1_index.css"/>
  7. <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js" ></script>
  8. <script type="text/javascript" src="/public/js/level1_config.js"></script>
  9. <script type="text/javascript" src="/public/js/level1_index.js"></script>
  10. </head>
  11. <body>
  12. <div class="jingshan">
  13. <span id="timebox">01天01時01分01秒</span>
  14. </div>
  15. </body>
  16. <script type="text/javascript" src="/public/js/level1_countdown.js" ></script>
  17. <script type="text/javascript">
  18. //動態加載js文件
  19. document.write("<s" + "cript type='text/javascript' src='/public/js/nocdn.js?ver=" + Math.random() + "'></s" + "cript>");
  20. </script>
  21. </html>

使用二級域名,用cdn緩存html頁面,css,js,圖片等

nocdn.js生成腳本


  1. <?php
  2.  
  3. $redis = new \Redis();
  4. if ($redis->connect('127.0.0.1','6379') == false) {
  5. die($redis->getLastError());
  6. }
  7.  
  8.  
  9.  
  10. //設置token
  11. $token=md5(rand(100,10000));
  12. $redis->set("token",$token);
  13.  
  14. $hl=fopen("public/js/nocdn.js","w");
  15.  
  16.  
  17. $js=<<<EOF
  18. var button = '<div class="jingshan">'+
  19. '<span id="timebox" class="start">秒殺已經開始</span>'+
  20. '<span id="qianggou"><a href="javascript:;" ><img src="/public/images/level1_button.jpg" alt="搶購按鈕"/></a></span></div>';
  21. $(".jingshan").html(button);
  22.  
  23. $(function(){
  24. var flag=1;
  25. $("#qianggou").click(function(){
  26. if(flag!=1){
  27. return ;
  28. }
  29. flag=2;
  30. var token='{$token}';
  31. var url="http://192.168.128.128/redis.php"
  32. $.ajax({
  33. type: "POST",
  34. url: url,
  35. data: "token="+token,
  36. success: function(msg){
  37. alert( "Data Saved: " + msg );
  38. }
  39. });
  40. })
  41.  
  42. })
  43. EOF;
  44. fwrite($hl, $js);
  45. fclose($hl);

主要生成nocdn.js文件的內容,用linux crontab設置定時腳本
內容主要是顯示秒殺的按鈕,生成隨機的參數,生成ajax的提交腳本,如果要跨域使用jsonp【推薦閱讀: js跨域4種解決方案

搶購代碼


  1. $redis = new \Redis();
  2.  
  3. if ($redis->connect('127.0.0.1','6379') == false) {
  4. die($redis->getLastError());
  5. }
  6.  
  7. //判斷用戶是否已經搶購
  8. if($redis->hexists("mywatchlist","user_id_")==1){
  9. exit("已經搶購");
  10. }
  11. //帶參數的url
  12. if($redis->get("token")!=$_GET['token']){
  13. exit("參數錯誤");
  14. }
  15.  
  16. $redis->watch("mywatchkey");//命令用于監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那么事務將被打斷
  17. $mywatchkey=$redis->get("mywatchkey");
  18. $limit=10;
  19. if($mywatchkey>=$limit){
  20. exit("活動結束");
  21. }
  22. $redis->multi();//事務塊內的多條命令會按照先后順序被放進一個隊列當中,最后由 EXEC 命令原子性(atomic)地執行。
  23. $redis->set("mywatchkey",$mywatchkey+1);
  24. //sleep(5);//測試watch
  25. $rob_result = $redis->exec();//按命令執行的先后順序排列。 當操作被打斷時,返回空值 nil,在php中成功返回array(0->1)失敗返回空
  26.  
  27. if($rob_result){
  28. //保證庫存,原子判斷,確保當兩個客戶同時訪問 Redis 服務器得到的是更新后的值
  29. if($redis->incr("stock")>$limit){
  30. echo "搶購失敗,請重試";
  31. }
  32. echo "搶購成功";
  33. //搶購成功
  34. //$redis->hSet("mywatchlist","user_id_".mt_rand(1, 9999),time());
  35. $redis->LPUSH("success",rand(1,20));
  36. }else{
  37. echo "搶購失敗,請重試";
  38. }
  39. exit;

主要是redis的watch,如果執行事務發現mywatchkey變動過就執行事務失敗,redis事務失敗不會回滾,代碼測試過
用ab測試沒有超賣的問題

上一篇:網站建設淺談php中使用websocket              下一篇:影響網站建設費用的主要原因有哪幾點

有什么赌大小的软件