zoukankan      html  css  js  c++  java
  • 关于PHP高并发抢购系统设计

    内容
    并发抢购系统注意事项
    高并发架构设计描述
    程序端核心代码实现
    订单流程mysql 端并发解决方案


    注意事项
    (1)高并发环境下,对于服务器cup、内存、网络宽带使用率会瞬间暴涨,需要注意对同服务器上其他应用的影响。(项目解耦,高并发应用独立部署)
    (2)服务器高负载运行,容易出现死机,重启服务器场景,要提前考虑内存(redis)数据备份与恢复,防止用户抢购数据丢失.
    (3)高并发应用首先要注重稳定性,其次是性能上优化.


    (4) 一台服务器能够支持多少并发量
    nginx服务为例:
    worker_processes 8;
    worker_rlimit_nofile 102400;
    use epoll;
    worker_connections 102400;
    ulimit -n
    cat /proc/sys/fs/file-max 


    架构设计

    (1)LVS服务, 做负载均衡调度, 采用RD模式, 通过股修改数据包的目的MAC地址实现转发,该方式性能好, 对并发高应用,适合大规模部署负载均衡机器;抗负载能力强、是工作在网络4层仅作分发之用,没有流量的产生;工作稳定,自身有完整的双机热备方案
    (2)keepalive(vrrp协议方式) 做心跳检测,支持应用具有高可用性。
    (3)nginx工作在网络的7层,所以它可以针对http应用本身来做分流策略, 可用说对LVS负载的补充。nginx高效处理高并发请求在于采用异步非阻塞工作方式和epoll IO 模型。  
    (4)页面动态数据,用户数据,抢购商品数据采用Redis存储。
    (5)用户抢购记录标识存储在Redis服务器端。在nginx负载均衡端,应用lua脚本做用户抢购记录过滤。
    (6)real server端部署 nginx与php, 同时 real server 可以参与负载端调度。
    (7)mysql server cluster 端采用一主多从部署,master负载数据写及同步到slave, slave负责数据读取。推荐应用mysql代理组件atlas, 实现对php端对mysql读写透明操作。
    核心代码实现
    背景
    假设每个用户只允许抢购一件商品。
    预备数据
    抢购商品总数存入redis中, 比如十万个数据
    $redisObj = new redis();
    $redisObj->set('goods_amount', 1000000);
    $redis->watch('goods_amount'); //应用redis watch 乐观锁
    $amount = $redis->get('goods_amount');
    if($amount > 0)
    {
     $userInfo = $reids->get('user_info_crc32(url_token)', array('userId'=>120, '....')); 
     
      if(empty($userInfo)){
          
            $ret = $redis->multi() ->decr('goods_amount') ->exec();
          if($ret){
    $reids->set('user_info_crc32(url_token)', array('userId'=>120, '....')); 
           根据crc32(url_token)唯一索引创建改用户已抢过商品的标识。(同时标识可以设置一段时间有效期,例如10分钟);
        
    write("user_id", {user_id}_success.log);
          }else {
                    //提示抢购失败 
        }
     } else {
        $redis->unwatch(‘goods_amount');
        //提示抢购失败 
    } else {
        //抢购结束, 封闭入口
    }
    }


    (1)下一个抢购请求到来时,在nginx服务器lua端,检查googs_amount抢购商品数量,判断抢购有没有结束,在判断user_info_crc32(url_token)有没有抢过成功,如果成功跳转到下单页面,否则执行抢过流程。
    (2)抢购首页直接高并发静态资源存储在cdn 服务端, 来减轻服务端访问请求的压力
    mysql端并发解决
    (1)抢购商品数据预热,提前存储在redis中,比如商品名称,属性等等。
    (2)采用innodb 数据库引擎,在高并发场景读操作有优势,合理创建表结构,尽可能的减少链表查,可以适当设计表中冗余字段,sql查询能够必须走索引。
    (3)用户浏览商品详情页(需要在redis端做动态数据缓存) 
    (4)用户点击购买跳转到订单详情页(包括用户基本信息,商品信息,支付方式,积分消费等数据考虑对数据库并发查询压力,要采用redis缓存策略)
    (5)订单数据提前生成,user_id留空,同时通过redis lpush,把连续订单id,提前同步到redis分布式集群,redis集群支持心调检测,能够自动做服务奔溃切换。
    (6)用户提交订单后,  在redis服务lpop拿到一个订单id, 根据订单id条件更新用户user_id等信息。
       begin;
       update mt_account set user_id=100 where order_id=$orderId and user_id=0 li mit 1;
       commit;
     
  • 相关阅读:
    leetcode 之 Palindrome Partitioning
    虚拟机共享文件夹下tar
    leetcode 之 Excel Sheet Column Number
    AndroidHttpClient & jsoup 解析 正方教务系统
    查看android下的分区表
    ubuntukylin 下编译 android4.4
    android:layout_weight 和 android: weightSum的使用
    Intent 与Bundle的传值关系
    使用自定义的Toast
    SlideMenu例子解析2
  • 原文地址:https://www.cnblogs.com/lazb/p/6961615.html
Copyright © 2011-2022 走看看