精华内容
下载资源
问答
  • 多线程和高并发介绍 万次阅读 多人点赞
    2021-06-06 05:00:46

    多线程和高并发介绍


    前言

    本文主要是针对多线程和高并发的概念做了简单的描述,介绍了什么是多线程,什么是高并发,并且对多线程和高并发的关系做了比较描述。

    一、什么是多线程?

    1.多线程介绍

    什么是多线程,首先看下百度百科对多线程的定义;多线程(multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理或同时多线程处理器。在一个程序中,这些独立运行的程序片段叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”。

    2.多线程实现原理?

    实现多线程是采用一种并发执行机制。 并发执行机制原理: 简单地说就是把一个处理器划分为若干个短的时间片,每个时间片依次轮流地执行处理各个应用程序,由于一个时间片很短,相对于一个应用程序来说,就好像是处理器在为自己单独服务一样,从而达到多个应用程序在同时进行的效果 。 多线程就是把操作系统中的这种并发执行机制原理运用在一个程序中,把一个程序划分为若干个子任务,多个子任务并发执行,每一个任务就是一个线程。这就是多线程程序。

    3.白话文解释多线程

    举个例子,我们打开腾讯管家,腾讯管家本身就是一个程序,也就是说它就是一个进程,它里面有很多的功能,我们可以看下图,能查杀病毒、清理垃圾、电脑加速等众多功能。 按照单线程来说,无论你想要清理垃圾、还是要病毒查杀,那么你必须先做完其中的一件事,才能做下一件事,这里面是有一个执行顺序的。 如果是多线程的话,我们其实在清理垃圾的时候,还可以进行查杀病毒、电脑加速等等其他的操作,这个是严格意义上的同一时刻发生的,没有执行上的先后顺序。

    4.多线程存在的问题

    1.多线程存在线程安全问 2.死锁问题

    二、什么是高并发?

    1.高并发介绍

    首先看下百度百科对高并发的定义;高并发(High Concurrency)通常是指通过设计保证系统能够同时并行处理很多请求。通俗来讲,高并发是指在同一个时间点,有很多用户同时的访问同一 API 接口或者 Url 地址。它经常会发生在有大活跃用户量,用户高聚集的业务场景中。

    2.如何提升系统的并发能力

    高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。 提高系统并发能力的方式,方法论上主要有两种:垂直扩展(Scale Up)与水平扩展(Scale Out)。前者垂直扩展可以通过提升单机硬件性能,或者提升单机架构性能,来提高并发性,但单机性能总是有极限的,互联网分布式架构设计高并发终极解决方案还是后者:水平扩展。 互联网分层架构中,各层次水平扩展的实践又有所不同: (1)反向代理层可以通过“DNS轮询”的方式来进行水平扩展; (2)站点层可以通过nginx来进行水平扩展; (3)服务层可以通过服务连接池来进行水平扩展; (4)数据库可以按照数据范围,或者数据哈希的方式来进行水平扩展; 各层实施水平扩展后,能够通过增加服务器数量的方式来提升系统的性能,做到理论上的性能无限

    三、多线程和高并发

    “高并发和多线程”总是被一起提起,给人感觉两者好像相等,实则 高并发 ≠ 多线程   多线程是完成任务的一种方法,高并发是系统运行的一种状态,通过多线程有助于系统承受高并发状态的实现。   高并发是一种系统运行过程中遇到的一种“短时间内遇到大量操作请求”的情况,主要发生在web系统集中大量访问或者socket端口集中性收到大量请求(例如:12306的抢票情况;天猫双十一活动)。该情况的发生会导致系统在这段时间内执行大量操作,例如对资源的请求,数据库的操作等。如果高并发处理不好,不仅仅降低了用户的体验度(请求响应时间过长),同时可能导致系统宕机,严重的甚至导致OOM异常,系统停止工作等。如果要想系统能够适应高并发状态,则需要从各个方面进行系统优化,包括,硬件、网络、系统架构、开发语言的选取、数据结构的运用、算法优化、数据库优化……而多线程只是其中解决方法之一。

    总结

    本文主要是针对多线程和高并发的概念做了简单的描述,介绍了什么是多线程,什么是高并发,并且对多线程和高并发的关系做了比较描述。下一节主要针对如何保证多线程的线程安全,如何防止死锁以及synchronized关键字的使用进行讲解。

    更多相关内容
  • PHP解决高并发问题

    万次阅读 多人点赞 2020-05-27 12:10:04
    我们通常衡量一个Web系统的吞吐率的指标是QPS(Query Per Second,每秒处理请求数),解决每秒数万次的高并发场景,这个指标非常关键。举个例子,我们假设处理一个业务请求平均响应时间为100ms,同时,系统内有20台...

    举个例子,高速路口,1秒钟来5部车,每秒通过5部车,高速路口运作正常。突然,这个路口1秒钟只能通过4部车,车流量仍然依旧,结果必定出现大塞车。(5条车道忽然变成4条车道的感觉)

    同理,某一个秒内,20*500个可用连接进程都在满负荷工作中,却仍然有1万个新来请求,没有连接进程可用,系统陷入到异常状态也是预期之内。

    14834077821.jpg

    其实在正常的非高并发的业务场景中,也有类似的情况出现,某个业务请求接口出现问题,响应时间极慢,将整个Web请求响应时间拉得很长,逐渐将Web服务器的可用连接数占满,其他正常的业务请求,无连接进程可用。

    更可怕的问题是,是用户的行为特点,系统越是不可用,用户的点击越频繁,恶性循环最终导致“雪崩”(其中一台Web机器挂了,导致流量分散到其他正常工作的机器上,再导致正常的机器也挂,然后恶性循环),将整个Web系统拖垮。

    重启与过载保护

    如果系统发生“雪崩”,贸然重启服务,是无法解决问题的。最常见的现象是,启动起来后,立刻挂掉。这个时候,最好在入口层将流量拒绝,然后再将重启。如果是redis/memcache这种服务也挂了,重启的时候需要注意“预热”,并且很可能需要比较长的时间。

    秒杀和抢购的场景,流量往往是超乎我们系统的准备和想象的。这个时候,过载保护是必要的。如果检测到系统满负载状态,拒绝请求也是一种保护措施。在前端设置过滤是最简单的方式,但是,这种做法是被用户“千夫所指”的行为。更合适一点的是,将过载保护设置在CGI入口层,快速将客户的直接请求返回

    高并发下的数据安全

    我们知道在多线程写入同一个文件的时候,会存现“线程安全”的问题(多个线程同时运行同一段代码,如果每次运行结果和单线程运行的结果是一样的,结果和预期相同,就是线程安全的)。如果是MySQL数据库,可以使用它自带的锁机制很好的解决问题,但是,在大规模并发的场景中,是不推荐使用MySQL的。秒杀和抢购的场景中,还有另外一个问题,就是“超发”,如果在这方面控制不慎,会产生发送过多的情况。我们也曾经听说过,某些电商搞抢购活动,买家成功拍下后,商家却不承认订单有效,拒绝发货。这里的问题,也许并不一定是商家奸诈,而是系统技术层面存在超发风险导致的。

    1. 超发的原因

    假设某个抢购场景中,我们一共只有100个商品,在最后一刻,我们已经消耗了99个商品,仅剩最后一个。这个时候,系统发来多个并发请求,这批请求读取到的商品余量都是99个,然后都通过了这一个余量判断,最终导致超发。(同文章前面说的场景)

    14834077822.jpg

    在上面的这个图中,就导致了并发用户B也“抢购成功”,多让一个人获得了商品。这种场景,在高并发的情况下非常容易出现。

    优化方案1:将库存字段number字段设为unsigned,当库存为0时,因为字段不能为负数,将会返回false

     <?php
     //优化方案1:将库存字段number字段设为unsigned,当库存为0时,因为字段不能为负数,将会返回false
     include('./mysql.php');
     $username = 'wang'.rand(0,1000);
     //生成唯一订单
     function build_order_no(){
       return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
     }
     //记录日志
     function insertLog($event,$type=0,$username){
         global $conn;
         $sql="insert into ih_log(event,type,usernma)
         values('$event','$type','$username')";
         return mysqli_query($conn,$sql);
     }
     function insertOrder($order_sn,$user_id,$goods_id,$sku_id,$price,$username,$number)
     {
           global $conn;
           $sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price,username,number)
           values('$order_sn','$user_id','$goods_id','$sku_id','$price','$username','$number')";
          return  mysqli_query($conn,$sql);
     }
     //模拟下单操作
     //库存是否大于0
     $sql="select number from ih_store where goods_id='$goods_id' and sku_id='$sku_id' ";
     $rs=mysqli_query($conn,$sql);
     $row = $rs->fetch_assoc();
       if($row['number']>0){//高并发下会导致超卖
           if($row['number']<$number){
             return insertLog('库存不够',3,$username);
           }
           $order_sn=build_order_no();
           //库存减少
           $sql="update ih_store set number=number-{$number} where sku_id='$sku_id' and number>0";
           $store_rs=mysqli_query($conn,$sql);
           if($store_rs){
               //生成订单
               insertOrder($order_sn,$user_id,$goods_id,$sku_id,$price,$username,$number);
               insertLog('库存减少成功',1,$username);
           }else{
               insertLog('库存减少失败',2,$username);
           }
       }else{
           insertLog('库存不够',3,$username);
       }
     ?>
    
    1. 悲观锁思路

    解决线程安全的思路很多,可以从“悲观锁”的方向开始讨论。

    悲观锁,也就是在修改数据的时候,采用锁定状态,排斥外部请求的修改。遇到加锁的状态,就必须等待。

    14834077833.jpg

    虽然上述的方案的确解决了线程安全的问题,但是,别忘记,我们的场景是“高并发”。也就是说,会很多这样的修改请求,每个请求都需要等待“锁”,某些线程可能永远都没有机会抢到这个“锁”,这种请求就会死在那里。同时,这种请求会很多,瞬间增大系统的平均响应时间,结果是可用连接数被耗尽,系统陷入异常。

    优化方案2:使用MySQL的事务,锁住操作的行

     <?php
     //优化方案2:使用MySQL的事务,锁住操作的行
     include('./mysql.php');
     //生成唯一订单号
     function build_order_no(){
       return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
     }
     //记录日志
     function insertLog($event,$type=0){
         global $conn;
         $sql="insert into ih_log(event,type)
         values('$event','$type')";
         mysqli_query($conn,$sql);
     }
     //模拟下单操作
     //库存是否大于0
     mysqli_query($conn,"BEGIN");  //开始事务
     $sql="select number from ih_store where goods_id='$goods_id' and sku_id='$sku_id' FOR UPDATE";//此时这条记录被锁住,其它事务必须等待此次事务提交后才能执行
     $rs=mysqli_query($conn,$sql);
     $row=$rs->fetch_assoc();
     if($row['number']>0){
         //生成订单
         $order_sn=build_order_no();
         $sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
         values('$order_sn','$user_id','$goods_id','$sku_id','$price')";
         $order_rs=mysqli_query($conn,$sql);
         //库存减少
         $sql="update ih_store set number=number-{$number} where sku_id='$sku_id'";
         $store_rs=mysqli_query($conn,$sql);
         if($store_rs){
           echo '库存减少成功';
             insertLog('库存减少成功');
             mysqli_query($conn,"COMMIT");//事务提交即解锁
         }else{
           echo '库存减少失败';
             insertLog('库存减少失败');
         }
     }else{
       echo '库存不够';
         insertLog('库存不够');
         mysqli_query($conn,"ROLLBACK");
     }
     ?>
    
    1. FIFO队列思路

    那好,那么我们稍微修改一下上面的场景,我们直接将请求放入队列中的,采用FIFO(First Input First Output,先进先出),这样的话,我们就不会导致某些请求永远获取不到锁。看到这里,是不是有点强行将多线程变成单线程的感觉哈。

    14834077834.jpg

    然后,我们现在解决了锁的问题,全部请求采用“先进先出”的队列方式来处理。那么新的问题来了,高并发的场景下,因为请求很多,很可能一瞬间将队列内存“撑爆”,然后系统又陷入到了异常状态。或者设计一个极大的内存队列,也是一种方案,但是,系统处理完一个队列内请求的速度根本无法和疯狂涌入队列中的数目相比。也就是说,队列内的请求会越积累越多,最终Web系统平均响应时候还是会大幅下降,系统还是陷入异常。

    1. 文件锁的思路
      对于日IP不高或者说并发数不是很大的应用,一般不用考虑这些!用一般的文件操作方法完全没有问题。但如果并发高,在我们对文件进行读写操作时,很有可能多个进程对进一文件进行操作,如果这时不对文件的访问进行相应的独占,就容易造成数据丢失

    优化方案4:使用非阻塞的文件排他锁

     <?php
     //优化方案4:使用非阻塞的文件排他锁
     include ('./mysql.php');
     //生成唯一订单号
     function build_order_no(){
       return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
     }
     //记录日志
     function insertLog($event,$type=0){
         global $conn;
         $sql="insert into ih_log(event,type)
         values('$event','$type')";
         mysqli_query($conn,$sql);
     }
     $fp = fopen("lock.txt", "w+");
     if(!flock($fp,LOCK_EX | LOCK_NB)){
         echo "系统繁忙,请稍后再试";
         return;
     }
     //下单
     $sql="select number from ih_store where goods_id='$goods_id' and sku_id='$sku_id'";
     $rs =  mysqli_query($conn,$sql);
     $row = $rs->fetch_assoc();
     if($row['number']>0){//库存是否大于0
         //模拟下单操作
         $order_sn=build_order_no();
         $sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
         values('$order_sn','$user_id','$goods_id','$sku_id','$price')";
         $order_rs =  mysqli_query($conn,$sql);
         //库存减少
         $sql="update ih_store set number=number-{$number} where sku_id='$sku_id'";
         $store_rs =  mysqli_query($conn,$sql);
         if($store_rs){
           echo '库存减少成功';
             insertLog('库存减少成功');
             flock($fp,LOCK_UN);//释放锁
         }else{
           echo '库存减少失败';
             insertLog('库存减少失败');
         }
     }else{
       echo '库存不够';
         insertLog('库存不够');
     }
     fclose($fp);
      ?>
    
     <?php
     //优化方案4:使用非阻塞的文件排他锁
     include ('./mysql.php');
     //生成唯一订单号
     function build_order_no(){
       return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
     }
     //记录日志
     function insertLog($event,$type=0){
         global $conn;
         $sql="insert into ih_log(event,type)
         values('$event','$type')";
         mysqli_query($conn,$sql);
     }
     $fp = fopen("lock.txt", "w+");
     if(!flock($fp,LOCK_EX | LOCK_NB)){
         echo "系统繁忙,请稍后再试";
         return;
     }
     //下单
     $sql="select number from ih_store where goods_id='$goods_id' and sku_id='$sku_id'";
     $rs =  mysqli_query($conn,$sql);
     $row = $rs->fetch_assoc();
     if($row['number']>0){//库存是否大于0
         //模拟下单操作
         $order_sn=build_order_no();
         $sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
         values('$order_sn','$user_id','$goods_id','$sku_id','$price')";
         $order_rs =  mysqli_query($conn,$sql);
         //库存减少
         $sql="update ih_store set number=number-{$number} where sku_id='$sku_id'";
         $store_rs =  mysqli_query($conn,$sql);
         if($store_rs){
           echo '库存减少成功';
             insertLog('库存减少成功');
             flock($fp,LOCK_UN);//释放锁
         }else{
           echo '库存减少失败';
             insertLog('库存减少失败');
         }
     }else{
       echo '库存不够';
         insertLog('库存不够');
     }
     fclose($fp);
      ?>
    
    1. 乐观锁思路

    这个时候,我们就可以讨论一下“乐观锁”的思路了。乐观锁,是相对于“悲观锁”采用更为宽松的加锁机制,大都是采用带版本号(Version)更新。实现就是,这个数据所有请求都有资格去修改,但会获得一个该数据的版本号,只有版本号符合的才能更新成功,其他的返回抢购失败。这样的话,我们就不需要考虑队列的问题,不过,它会增大CPU的计算开销。但是,综合来说,这是一个比较好的解决方案。

    在这里插入图片描述
    有很多软件和服务都“乐观锁”功能的支持,例如Redis中的watch就是其中之一。通过这个实现,我们保证了数据的安全。

    优化方案5:Redis中的watch

     <?php
     $redis = new redis();
      $result = $redis->connect('127.0.0.1', 6379);
      echo $mywatchkey = $redis->get("mywatchkey");
     /*
       //插入抢购数据
      if($mywatchkey>0)
      {
          $redis->watch("mywatchkey");
       //启动一个新的事务。
         $redis->multi();
        $redis->set("mywatchkey",$mywatchkey-1);
        $result = $redis->exec();
        if($result) {
           $redis->hSet("watchkeylist","user_".mt_rand(1,99999),time());
           $watchkeylist = $redis->hGetAll("watchkeylist");
             echo "抢购成功!<br/>";
             $re = $mywatchkey - 1;  
             echo "剩余数量:".$re."<br/>";
             echo "用户列表:<pre>";
             print_r($watchkeylist);
        }else{
           echo "手气不好,再抢购!";exit;
        } 
      }else{
          // $redis->hSet("watchkeylist","user_".mt_rand(1,99999),"12");
          //  $watchkeylist = $redis->hGetAll("watchkeylist");
             echo "fail!<br/>";   
             echo ".no result<br/>";
             echo "用户列表:<pre>";
           //  var_dump($watchkeylist); 
      }*/
     $rob_total = 100;   //抢购数量
     if($mywatchkey<=$rob_total){
         $redis->watch("mywatchkey");
         $redis->multi(); //在当前连接上启动一个新的事务。
         //插入抢购数据
         $redis->set("mywatchkey",$mywatchkey+1);
         $rob_result = $redis->exec();
         if($rob_result){
              $redis->hSet("watchkeylist","user_".mt_rand(1, 9999),$mywatchkey);
             $mywatchlist = $redis->hGetAll("watchkeylist");
             echo "抢购成功!<br/>";
           
             echo "剩余数量:".($rob_total-$mywatchkey-1)."<br/>";
             echo "用户列表:<pre>";
             var_dump($mywatchlist);
         }else{
               $redis->hSet("watchkeylist","user_".mt_rand(1, 9999),'meiqiangdao');
             echo "手气不好,再抢购!";exit;
         }
     }
     ?>
    
    展开全文
  • 目标:从0到1构建一个高并发的秒杀系统 三个阶段 从0到1构建一个电商系统 从0到1构建秒杀系统 从0到1构建高并发秒杀系统 为了完成这个目标,我们需要知道几个前提 什么是电商 什么是秒杀 什么是高并发 如何设计...

    秒杀项目

    目标:从0到1构建一个高并发的秒杀系统

    三个阶段

    • 从0到1构建一个电商系统
    • 从0到1构建秒杀系统
    • 从0到1构建高并发秒杀系统

    为了完成这个目标,我们需要知道几个前提

    1. 什么是电商
    2. 什么是秒杀
    3. 什么是高并发
    4. 如何设计高并发秒杀系统

    什么是电商

    商家通过互联网(软件)的方式来销售商品。就是电商。

    例如,我们所看到的,什么淘宝,京东之类。良品铺子,都可以在网上进行购买他们的商品,这些就是电商

    电商类型

    个人电商:

    ​ 软件只买一家门店的商品就是个人电商,

    ​ 例如:良品铺子通过软件买的商品,各位同学去开一家门店,然后通过软件来卖自家的商品,就是电商

    平台电商

    ​ 软件卖多家门店的商品就是平台电商,例如:淘宝,京东就属于这一类

    如何开发电商

    为什么会出现电商

    首先,我们要弄明白一点,没有电商之前,我们是通过门店来销售商品,还有的是通过会销等其他方式,我们只讨论门店销售

    这一块。

    这个时候,随着互联网的出现,越来越多的人发现门店销售有限,只能够销售一方,这个时候就有人想,如果我们想将商品销售到全中国,于是有人准备去开很多分店去解决,但是发现,成本太高。这个时候,有人就想,我们想销售到全中国的同时,想大量的降低成本。所以大家发现互联网发送一个消息全中国的人都可以收到,于是,马云说,我们来尝试一下吧。成功我就发了,不成功 ,我就做杭州教英语,继续老师。没有想到,成功了,所以了就出现了电商。

    我为什么要说这段故事呢,很简单,大家有没有发现,电商的前身就是门店,他们两个是不同场合不同的名称。就好像黑白无常一样,知道了黑,就知道了白。

    所以,如果我们想开发一个电商项目,就必须知道门店是如何经营的,也就是说,我们必须知道门店他们是如何卖商品的。有哪些角色组成。

    大家好好想一下,门店内卖商品的流程,我就比如去良品铺子进行

    消费者,商品,付钱,发票单(个人电商)

    消费者----->选择商品------>付钱-------->发票单(什么时候买的什么商品)

    我们就可以得到最简单的商品购买流程。(个人大型电商)

    如果出现超市之类的,加一个购物车,先放到购物车,然后一起付钱

    消费者----->选择商品----->购物车------>付钱-------->发票单(什么时候买的什么商品)

    如果是去商场之类的,就加一个商家(平台电商)

    消费者----->商家------>选择商品----->购物车------>付钱-------->发票单(什么时候买的什么商品)

    模块设计

    我们以开发一个最简单的电商项目为例

    消费者----->选择商品------>付钱-------->发票单(什么时候买的什么商品)

    我们可以得出这4个模块

    • 用户模块
    • 商品模块
    • 支付模块
    • 订单模块

    不管多复杂的电商,所有的都是在这个基础上扩展出来的新的模块,例如:购物车,商家,发货,评价,退款,秒杀等等

    什么是秒杀

    秒杀就是在很短时间内,卖出所有的商品。

    就好比,我们在淘宝网看到的商品,京东上看到的秒杀,我们扩展一下,还有很多类似的场景

    春节,我们在12306抢票,我们在支付宝抢红包,在微服务摇一摇等等都是秒杀的场景。

    秒杀类型

    • 1秒秒杀类型

    ​ 1秒类秒杀有限商品

    • 分钟秒杀类型

    ​ 一分钟之类秒杀有限商品

    • 小时秒杀类型

    ​ 1小时之类秒杀所有商品

    • 1天内秒杀类型

    ​ 1天之类秒杀所有商品

    如何实现秒杀系统

    为什么会出现秒杀

    我们刚才看到,秒杀就是在有限的时间秒杀商品,说明秒杀针对的对象还是商品

    说明什么,说明秒杀是在商品的基础上扩展出来的。只是加了有一个时间限制。所以我们可以得到秒杀商品是属于商品的一个类型,属于什么类型呢,属于商品营销类型,秒杀本质上就是一种营销活动,所以我们可以得出秒杀就是商品的营销类型。

    因此,如果我们要设计一个秒杀系统,我们必须知道电商的逻辑

    消费者----->选择商品------>付钱-------->发票单(什么时候买的什么商品)

    消费者----->秒杀商品(时间限制)------>付钱-------->发票单(什么时候买的什么商品)

    模块设计

    所有秒杀系统设计还是和原有逻辑没有变化,只是把普通商品替换了。

    其实我们只需要设计一个模块即可,我们可以把时间设置到秒杀模块里面,但是时间有很多类型,很多商品都需要设置时间

    秒杀模块

    时间模块

    秒杀系统过渡到高并发

    如果我们想将一个秒杀系统设计成为一个高并发的秒杀系统,光有这些设计是不够的,我们还需要知道什么是高并发

    前面我们讲过了相应的高并发知识点,但是我们在这里还是要回顾一下高并发的知识点。

    什么是高并发

    高并发就是在1秒内用户请求非常大,服务器能够处理在1秒之内能够这些请求,不会导致服务器宕机。就是高并发。

    高并发指的是1秒内用户用户请求数,高并发能力就是指服务器处理能力。

    多大才算高并发

    那么什么用户达到多少请求才算是高并发呢?

    答案:这个问题的答案不是指系统处理的一个数字。

    为什么会有高并发

    一般我们开发一个项目,都会把所有的模块全部一次性放到一个项目中进行开发,然后进行部署,最后进行优化。

    如果我们的系统目前并发量为300,也就是每秒能够处理300个请求。

    随着用户请求数,在1秒内出来的请求,发出600并发,这个时候,系统变得非常慢。接下来,我们就开始优化,如何保证系统能够处理600个并发量,

    如果我们优化后,单机可以达到600并发量的出来,

    但是,用户数是不稳定的,如果用户在1秒内请求持续加大,达到了1000千,

    我们接下来继续优化系统,发现系统的1秒最高并发量为600,大了就响应变慢,甚至宕机了。

    这个时候,我们又开始优化,如何 保证系统能够处理1000并发量。

    随着用户数,持续增大,到达45

    42·9 2000,10000,10W,100W持续增加,那我们系统如何能处理这么大的请求量呢 ?

    答案:继续优化。

    现在我们发现系统处理的请求数是一个持续的问题,不是一劳永逸的问题。

    来看一个场景:

    固态硬盘SSD(Solid State Disk)说:我读取和写入高达 1000MB/秒

    mysql说:我单机TPS10000+

    nginx说:我单机QPS10W+

    静儿说:给我一台56核200G高配物理机,我可以创建一个单机QPS1000W
    TPS和QPS的介绍

    TPS:是Transactions Per Second的缩写,也就是事务数/秒。它是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数。
    
    QPS:是Queries Per Second的缩写,意思是每秒查询率,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。
    
    区别及理解:
    
    1、TPS即每秒处理事务数,包括:”用户请求服务器”、”服务器自己的内部处理”、”服务器返回给用户”,这三个过程,每秒能够完成N个这三个过程,TPS也就是32、QPS基本类似于TPS,但是不同的是,对于一个页面的一次访问,形成一个TPS;但一次页面请求,可能产生多次对服务器的请求,服务器对这些请求,就可计入QPS之中。
    
    3、一般的,评价系统性能均以每秒钟完成的技术交易的数量来衡量。系统整体处理能力取决于处理能力最低模块的TPS值。
    
    4、QPS对应fetches/sec,即每秒的响应请求数,也即是最大吞吐能力。
    

    总结

    如果硬是要说高并发有一个标准,就是超过了单机处理的最大并发量,就算是高并发

    高并发的本质不是「多大算高并发」的一个数字,而是从架构上、设计上、编码上怎么来保证或者解决由并发引起的问题。

    当别人问你:“做过高并发吗?”回答者完全可以描述自己系统的各项指标,然后开始叙述自己对系统中对预防、解决并发问题作出的思考和行动。

    高并发量级

    高并发量级一般是指系统能够在一天处理的请求数

    • 千万级并发
    • 亿级并发
    • 10亿级并发

    服务器并发处理能力

    1秒内能够响应的请求数。这个数有多大,才是服务器并发能力

    如何实现高并发

    拆分原则

    1. 系统角度:按照系统功能/业务功能拆分,比如商品系统,购物车系统,结算系统,订单系统等
    2. 功能角度:对一个系统功能进行再次拆分,比如,优惠券系统可以拆分为后台劵创建系统,领劵系统,用劵系统
    3. ​ 读写角度:根据读写比例特征进行拆分,比如,商品系统,交易的各个系统都会读取数据,读的流量大于写,因此可以拆分成商品写服务,商品读服务,读服务可以考虑使用缓存提升性能,写的量太大,需要考虑分库分表,有些聚合读写的场景,如商品详情页,可考虑数据异构拆分系统,将分散在多处的数据聚合在一起存储,以提升系统的性能和可靠性。
    4. aop角度:根据访问特征,按照AOP进行拆分,比如,商品详情页可以拆分为CDN,页面渲染系统,CDN就是一个AOP系统,
    5. 模块角度:比如,按照基础或者代码维护特征进行拆分,如基础模块分库分表,数据库连接池等,代码结构一般按照三层架构(Web Service
      DAO)进行划分

    无状态原则

    ​ 如果设计的系统是无状态的,那么应用就非常容易水平扩展,实际生产环境可能是这样的,应用无状态,配置文件有状态,比如,不同的机房需要读取不同的数据源,此时,就需要通过配置文件或配置中心指定。

    服务化原则

    ​ 首先,判断是不是只需要简单的单点远程服务调用,单机不行集群是不是就可以解决,在客户端注册多台机器并使用Nginx进行负载均衡是不是就可以解决?

    ​ 总结为:进程内服务------>单机远程服务------>集群手动注册服务-------->自动注册和发现服务--------->服务的分组/隔离/路由/------>服务治理

    消息队列原则

    ​ 消息队列用来解耦一些不需要同步调用的服务或者订阅一些自己系统关关系的变化。

    ​ 使用消息队列可以实现服务解耦(一对一消费,一对多消费),异步处理,流量削峰/缓冲等

    ​ 比如:电商系统中的交易数据,有非常多的系统关系并订阅该数据。

    ​ 比如:订单生产系统

    缓存原则

    ​ 本地缓存:内存缓存,属于进程的缓存。

    ​ 本地分布式缓存:内存缓存,多进程共享,但是通过内网进行访问的缓存。

    ​ 分布式缓存:外部内存缓存,多进程共享,但是通过外网进行访问的缓存。

    异步并发化原则

    ​ 假设一个读服务需要如下数据,数据A,数据B,数据C,数据D,数据E 时间分别为10ms,15ms,10ms,20ms,5ms,

    ​ 如果串行读取,需要花费60ms,

    ​ 如果数据C依赖A,B,数据D谁 也不依赖,数据E依赖数据C,那么就可以直接并发读取A,B,D ,AB被C读取,然后再读取E,总读取时间为30ms,性能优化了一倍。

    如何设计秒杀高并发系统

    前提是我们必须要知道目前我们的系统是2000万秒杀20万手机。真正的并发量是多少。

    计算2000万的并发量

    每台服务器每秒处理请求的数量=((80%总PV量)/(24小时60分60秒40%)) / 服务器数量 。
    其中关键的参数是80%、40%。表示一天中有80%的请求发生在一天的40%的时间内。24小时的40%是9.6小时,有80%的请求发生一天的9.6个小时当中(很适合互联网的应用,白天请求多,晚上请求少)。

    一天时间

    如果我们要求2000万人在1天内抢完20万个手机。

    平均值:20000000 / 86400 = 232/s

    峰值:20000000 * 80% / 86400 * 40 = 232/s

    ​ 16000000/34560 = 463/s

    一个小时

    计算每秒服务器每秒需要处理的数量

    平均值:20000000 / 16060 =5556/s (QPS)

    峰值:16000000/1440 = 13889/s(QPS)

    峰值:16000000/720 = 27778/s(QPS)

    总结

    好像看起来是一条水平线,可是用户不听我们的呀,我们必须得算出一个峰值呀,

    这样才能够算是真实的,目前有一个

    假如目前aspnetcore项目每秒能够处理500个并发

    大家可以估算一下,需要多少台机器

    答案:56台服务器。

    可是这只是我们的一个估算,我们该如何知道真实的呢?

    两个前提,

    1、电商系统

    2、秒杀系统

    那么,我们如何设计这些系统呢?

    电商系统设计

    用户模块

    商品模块

    支付模块

    订单模块

    秒杀系统设计

    秒杀模块

    时间模块

    高并发秒杀系统相关技术

    相关技术:微服务,webapi aspnetcore,restful ,缓存,消息队列,限流,nginx,docker k8s,服务治理,IdentityServer4 mysql linux 自己研发小框架。

    相关工具:jmeter

    展开全文
  • 最实用的高并发任务执行架构设计 | 架构篇

    万次阅读 多人点赞 2021-10-23 01:14:16
    高并发任务执行架构 需求场景 业务架构设计 技术架构设计 初始设计 演化阶段一 演化阶段二 演化阶段三 代码设计 总结 前言 随着互联网与软件的发展,除了程序员,架构师也是越来越火的职业。他们伴随着...

    目录

    前言

    高并发任务执行架构

    需求场景

    业务架构设计

    技术架构设计

    初始设计

    演化阶段一

    演化阶段二

    演化阶段三

    代码设计

    总结


    前言

    随着互联网与软件的发展,除了程序员,架构师也是越来越火的职业。他们伴随着项目的整个生命过程,他们更像是传统工业的设计师,将项目当做生命一般细心雕琢。

    目前对于项目架构而言,基本都会需要设计的几个架构。

    1、业务架构

    项目或者产品的市场定位、需求范围、作用场景都是需要在项目启动初期进行系统性分析的。在设计业务架构中,架构师还需要明确角色。我看过很多关于架构的文章,谈到角色的很少。

    什么是角色?

    例如:商场作为一个整体系统,角色就有消费者、店员、收费员、保安等等。各个角色完成好自己角色所需要承担的任务,整体系统就能完美的运行。

    对应到软件系统中,根据产品的定位和需求,也会有着对照的角色,比如:用户、数据审核者、产品制作者、运维人员等。在项目启动初期,架构师需要对项目中的每个角色做好职责定位,我相信在这点上,大部分开发同学在工作中,或多或少都有过职责不明确带来的困扰

     

    2、技术架构

    在软件项目研发过程中,我们会用到许多外部组件。在使用组件中,架构师必须结合业务需求合理的选择各个组件。项目是个生命,她会成长,架构师需要明白如果一开始就选择重量级组件会让还是个孩童的项目不受重负,架构师也需要明白如果技术架构的设计不具备拓展性,那么这个孩子无法茁壮成长。所以技术架构尤为重要。

     

    3、物理架构

    物理架构又叫做部署架构,项目产品如果要在生产环境稳定运行,一个稳定又高效的物理架构是必不可少的。而且往往物理架构和技术架构是相辅相成的,性能监控、异常告警、业务日志等等设计,都是为了让项目做更好的自己。

    高并发任务执行架构

    在我十年的工作中,业务相关、中间件、大数据都有做过。本文主要分享一下高并发任务执行框架设计,会由浅入深的讲述一下设计演化过程。如果你不只是想做业务后端开发,那么本文会给你一个全新的视野。

    需求场景

    我们列一下该项目的需求场景,看看工作中是否遇到过。

    1、有个复杂的数据需要制作,而且制作的时间很长,无法让请求方持续等待。所以请求方只能给你个回调地址,需要你完成这个制作后将产物通知他。

    2、复杂的制作过程需要消耗资源,而且资源有限,无法无限量提供。如果你有接触过AI,就会比较了解资源有限的感受。除了ASR、TTS这类识别类型的AI功能能做到近实时的反馈,大部分的算法在运行的时候都会消耗整张显卡,而且耗时很长。

    初看场景,很多后端可能会第一时间想到elastic-job(一个分布式任务调度框架)。即便你熟悉使用elastic-job,一开始就选择重框架是不是有种杀鸡用牛刀的感觉。不着急,我们一步步分析,一步步设计。

    业务架构设计

    高度抽象一下我们的业务,对产品设计者而言,貌似是个简单的不能再简单的东西。等到了技术架构,我们深入分析其中演化的功能点,就会发现这是个庞大的机器。我们先给他起个简单的名字:Task Execution Engine(缩写:TEE)

    技术架构设计

    下面我们开始进行核心模块的技术架构设计,按照我们的初始需求开始我们的设计旅程。

    初始设计

    设计说明:

    1、业务后端发出q1请求,我们首先需要对该请求的参数做矫正,为了可用性考虑。

    2、参数校验过后,给到执行引擎模块。执行引擎主要的职责有从资源表获取资源数据、将任务参数与资源参数封装到任务对象内、将任务提交线程池。有一点要说明执行引擎最好使用队列模式,任务先进队列,可以通过while循环方式或者定时线程池都可以,后面会推荐更好的。

    3、任务执行的状态与结果需要同步到数据库中,建议使用mysql

    小结:

    按照初始需求,该设计相对比较简单,完全够用了。但是按照产品的迭代,业务方的需求不会仅限于此。继续演化。

    演化阶段一

    随着业务的上线,业务端会马上迎来新的问题。

    1、由于提交的任务太多了,排在后面的任务迟迟无法等到自己获取到资源执行任务。当然我们可以完全靠增加资源来解决,但是资源的数量在产品前期是不可知的。所以需要有一些策略,比如让用户可以取消自己任务,而不是一直等待。

    2、任务的种类开始增加,业务端不满足于单一制作,开始要求多样化

    3、任务的执行过程开始需要用到其他资源,不再是一个资源对一个任务的模式了。

    4、任务的整体执行情况不可知,需要一定的量化分析,至少让业务组知道每天的任务成功率。

    按照需求进行第二版的设计,在尽量不改变原来整体设计的情况下,补充功能。

    设计说明:

    1、为了解决排队问题,增加了双队列算法来解决。用图解的方式解释一下双队列

    逻辑简单说明一下,任务优先提交至执行队列,引擎的定时读取队列的顺序优先为等待队列。如果等待队列中的任务可以获取所需资源,则立即启动线程执行,否则原封不动回到等待队列。引擎其次读取执行队列,如果无法获取资源则进入等待队列,如获取资源,则立即启动线程执行。

    那么取消队列,则只需要将队列中的任务踢出队列即可。在送回队里的过程中,一定要保证队列的有序性。

    2、创建了任务池,增加了任务封装层,在任务池中挑选需要执行的任务类。

    3、增加了策略机模块,添加资源调度策略,由资源调度策略堆任务所需资源合理分配。可以由业务方提供分配方案,尽可能保证任务的公平性。

    4、数据库增加统计表,可以考虑使用定时任务,将任务表的数据统计存入统计表

    小结

    现在看上去已经比较完善了,合理了任务调度、增加了任务种类、合理的资源调度,好像还不错。但是产品总会有新要求的,那么继续演化。

    演化阶段二

    渐渐的,你设计的引擎还不错。那么新的挑战来了。

    1、更多的业务方找到你,希望也使用你的项目进行任务制作,但是他们并不想共享资源,而是希望有自己的独立资源,和独立的队列。但并不是所有的资源都需要独立,一些可以支持高并发的资源,是可以共享的。简而言之,更多的业务方,由业务方为维度的独立队列,独立和共享的资源分配

    2、业务方找到你,说如果把任务1的结果给到任务2,其实就能拿到我要的结果。问题来了,原子任务要具备可以编排成复杂任务的能力

    3、任务的状态过程无法监控。OK,任务状态机

    4、既然大家都需要对接你的项目,能不能提供标准的sdk,我只需要引入就可以完美的对接你的系统。

    5、相同的任务参数,是不是制作出来的结果一致呢?那么是否需要增加结果缓存,降低对资源的消耗呢?

    6、完正的生产项目必然需要将日志、告警等关键信息传递出来,一旦发生问题可以马上定位到问题的起因。

    这些问题对于新人来说还是很有挑战的,需要对系统深层的含义有充足的理解。没事,我来好好来说下设计所需要掌握的知识点。

    设计说明:

    1、需要在资源表中区别资源类型,共享资源组所有业务组都可以使用,独立资源则资源具备业务标识。在执行引擎的队列管理中,也需要区分业务组,避免共用排队。这里给一个建议,共享的资源一定要是可以支持并发或者可以部署多个实例的,避免所有的业务组产品制作瘫痪

    2、增加了高级任务概念,高级任务可以将任意的原子任务进行组合编排,形成全新的任务。需要定义专属于TEE的语法规则。对语法规则引擎的开发,有一些建议。你可能会选择规则引擎,建议其实可以自己开发,毕竟语法不会太过复杂,没必要引入三方的引擎

    3、增加任务状态机,执行引擎在提交线程的同时,也想任务状态机提交任务线程信息。任务的进度状态可以同步给任务状态机中,同时一旦任务执行过长的时间,除了任务自己的超时机制外,也可由状态机的看门狗程序将卡死线程释放、资源回收

    4、研发属于TEE的SDK,作为内部系统不建议SDK增加鉴权模块。毕竟你对接的往往都是业务后端,鉴权不通过的话根本渗透不到TEE层面。给开发SDK一些建议,尽量引用较少的包,避免业务端引入带来的包冲突。SDK也需要添加一些回调Consumer或者Function,尽可能让业务端对接起来代码简单

    5、增加了缓存策略,可以设想一下,大部分情况下,相同的参数制作出来的结果也必然相同。使用redis,将任务参数与任务结果进行缓存,主键可以采用任务参数的MD5值。任务在提交给任务执行引擎前,检查缓存中是否已经存在结果。缓存的过期时间按照具体情况而定。

    6、增加日志系统和监控系统的对接,状态机与任务执行中的信息接入到日志系统中。对于日志系统的建议是,最好采用成熟的ELK架构。可以考虑两种方式

    a、将日志异步推送到消息队列(例如:kafka),使用flink将kafka存入es。

    b、使用logstash将日志内容清洗处理,推送到es。

    两种方式都可以,但是一定要异步推送日志,避免任务阻塞。

    告警系统的接入可以使用Prometheus,将TEE的指标信息开放出来,特别是告警信息。在Prometheus的告警监控规则中,可以将告警信息按照某些策略发送邮件或者短信,通知运维人员

    小结:

    做到这里,我们再看看我们的技术架构图,是不是感到很满足。但是这真的够了吗?

    演化阶段三

    随着业务愈发繁重,一个新的问题出现。

    1、TEE在本机运行很顺利,但是每个任务都是需要消耗线程的,单台模式线程必然不是无限的,总有吃满的时候。问题来了,TEE得支持分布式部署结构。但是有资源管理的存在,你无法通过加实例的方式来实现,因为资源调度必然混乱。

    2、假设TEE挂掉,则等于业务组此刻提交的任务均失败,容灾机制需要建立。

    到了这一步,很多小伙伴可能觉着一阵头大,分布式不是大数据的东西吗?不是的,不是大数据就不能分布式部署吗?就不能有主从节点吗?就不能有注册中心吗?要跨过内心的固有思想,我们往下看。

    设计说明:

    1、需要先将TEE项目做一下代码分解,将管理调度模块与任务执行模块拆解开了。消耗性能和线程较高的是任务执行模块,定义为TEE执行节点。消耗性能和线程较低,却需要参数校验、任务封装、资源调度、队列管理的是管理调度模块,定义为TEE管理节点。

    2、TEE执行节点可以多实例,形成节点池。管理节点可以考虑做成共享任务队列的管理池。这里有个难点,如何共享任务队列。建议使用zookeeper或者缓存方式,但是不管哪种方式都要注意使用集群,避免单点故障导致队列数据丢失。

    3、关于注册中心,可以使用开源组件,nacos、zookeeper都可以。在该架构设计中,其实注册中心并没有太多功能,如果你对自己有信心,可以尝试自己写一个注册中心,核心功能就是服务注册与心跳检测。可以用netty架构做一做,提高一下自己的代码能力。

    4、在管理池的调用方面,增加网关代理,可以使用nginx、konga等。主要功能是业务端调用的时候,随机打到管理节点上,就算一个管理节点挂了,也不会影响使用,保证了生产线的稳定

    小结:

    分布式架构,主从节点模式也好、哨兵模式也好、选举模式也好,按照自己的业务需求选择最适合自己的。不是大数据才有分布式,它是一种设计思想,要知道开发大数据组件的大佬们,也是一行行java写出来的。大佬们可以,为什么你不可以呢?

    代码设计

    在着手开发该系统的时候,我给大家一些代码开发的建议:

    1、定时任务的实现,从最简单的while死循环加sleep,到定时线程池,或者springboot的@Scheduled注解,都可以实现。我在这里推荐一下时间轮算法TimeWheel,有兴趣的可以去了解一下。

    2、异步消息处理,如果你只是想在项目内部使用消息总线,推荐使用guava包内的EventBus。按照消息的数量级,考虑使用RabbitMQ或者Kafka作为消息中间件。

    3、任务执行,推荐使用CompletableFuture进行异步非阻塞任务编程。

    4、在资源的使用中,可能存在多种协议类型http、ws、tcp等。所以代码设计中,尽可能提供完整全面的协议工具类。

    总结

    最近和一个同事闲聊的时候,他和我说了说最近面试高级研发的情况。总结一下,现在想招一个做过高并发场景的太难了,大部分人选只做业务相关。这让我想到了十年前,我刚工作的时候。那时候没有那么多框架,大部分功能需要看很多资料研究底层的原理与算法。随着软件行业的日益成熟,从以前拿着谷歌翻译看国外的组建说明,到从阿里云直接对接功能,软件研发的成本和时间也在大大缩短。渐渐失去了研究分析的动力,框架什么都有为什么要抓破脑袋自己写。

    怎么成长?怎么进步?

    上面给出的架构图,看上去都挺好理解。但真要自己去代码实现,中间各个环节出现的问题真的好解决吗?冰冻三尺,非一日之寒。没有日积月累的学习,是很难成功的。不要惧怕那些你看上去遥远的东西,获取你的几个晚上的学习,它就成了你最趁手的武器。对学习而言,难的永远不是过程,而是踏出第一步。

    高并发任务执行架构中,有一个模块看上去很不起眼,但是在你研发的过程就会发现他会给你制造大麻烦-资源调度。以后有时间我会单独做一篇关于资源调度的架构设计,与大家说道说道里面的坑。

    最后说一句:为什么不ban猛犸?

    展开全文
  • 高并发情况下你还在用Random生成随机数?

    万次阅读 多人点赞 2021-04-05 23:42:13
    为了改进这个问题,增强随机数生成器在高并发环境中的性能,于是乎,就有了ThreadLocalRandom——一个性能强悍的高并发随机数生成器。 ThreadLocalRandom继承自Random,根据里氏代换原则,这说明ThreadLocalRandom...
  • Java高并发解决方案

    万次阅读 多人点赞 2019-03-03 22:23:50
    电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。...在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个W...
  • 我是全网最硬核的高并发编程作者,CSDN最值得关注博主,全网最硬核的基于可视化的多数据源数据异构中间件作者,也许现在就是,也是不久的将来就是,大家同意吗?
  • 大家好,我是冰河~~ 在【精通高并发系列】的《实践出真知:全网最强秒杀系统架构解密!!》一文中,冰河详细的阐述了高并发秒杀系统的架构设计,也简单提到了如何扣减商品的库存。 也许不少小伙伴会问:扣减商品的...
  • java高并发下数据入库

    千次阅读 2021-08-24 16:03:54
    java高并发下数据批量入库 该服务利用线程池并结合缓存类来处理高并发下数据入库问题,做到实时数据存入redis和数据批量入库,使用的时候需要修改为自己的业务数据,该服务暂时适合下面两种情况: 1、达到设置的超时...
  • 一:nginx配置ip限流 1、限制访问... limit_conn perserver 100:对应的key是 $server_name,表示虚拟主机(server) 同时能处理并发连接的总数。注意,只有当 request header 被后端server处理后,这个连接才进行计数。
  • 一:相关依赖包 CSRedisCore 二:代码封装 /// <summary> /// ServiceCollection Redis扩展 /// </summary>...public static class RedisServiceCollectionExtensions ...typeparam name="con
  • 引入 中国网络上可以产生消费的活跃用户约2.4亿,互联网人数较多,基础人群大 ...于是在这个时代,高并发已经是每一家企业都要面临的。 假设高并发被解决了,在web容器的日志里你要记录些什么?分析渠道的流量的
  • 什么是高并发 ,详细讲解

    万次阅读 多人点赞 2018-08-30 13:38:58
    一、什么是高并发 高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。   高并发相关常用的一些指标有响应时间(Response ...
  • 处理高并发的六种方法

    万次阅读 多人点赞 2019-03-19 12:35:02
    处理高并发的六种方法 1:系统拆分,将一个系统拆分为多个子系统,用dubbo来搞。然后每个系统连一个数据库,这样本来就一个库,现在多个数据库,这样就可以抗高并发。 2:缓存,必须得用缓存。大部分的高并发场景,...
  • 一:首先安装如下两个包 IdentityServer4 IdentityServer4.EntityFramework 二:在用户微服务进行认证 services.AddIdentityServer() .AddDeveloperSigningCredential()// 1、配置签署证书 ....
  • 使用JMeter进行接口高并发测试

    千次阅读 2022-04-16 13:41:28
    一般的网络接口测试,功能性测试postman较为好用,需要测试高并发的情况下,可以用Jmeter来进行测试,postman是串行,而Jmeter可以多线程并行测试。
  • Redis高并发场景下秒杀超卖解决

    千次阅读 2022-04-11 12:01:04
    目录1 什么是秒杀2 为什么要防止超卖3 单体架构常规秒杀3.1 常规减库存代码3.2 模拟高并发3.3 超卖现象3.4 分析原因4 简单实现悲观乐观锁解决单体架构超卖4.1 悲观锁4.2 乐观锁4.3 redis锁setnx4.4 使用Redision5 ...
  • 一:相关依赖包 DotNetCore.CAP DotNetCore.CAP.Dashboard DotNetCore.CAP.InMemoryStorage DotNet... 注释,这性能在数据库里,性能并不会多少,需要把mq任务存储在缓存里,但会造成丢失,后续篇幅会说解决方案。
  • 面试题:高并发场景下,如何保证缓存与数据库一致性? 问题分析 我们日常开发中,对于缓存用的最多的场景就像下图一样,可能仅仅是对数据进行缓存,减轻数据库压力,缩短接口响应时间。 这种方案在不需要考虑...
  • JAVA高并发的三种实现

    万次阅读 多人点赞 2018-07-23 10:50:59
    是用它可以解决一切并发问题,但是,对于系统吞吐量要求更的话,我们这提供几个小技巧。帮助大家减小锁颗粒度,提高并发能力。 初级技巧-乐观锁 乐观锁使用的场景是,读不会冲突,写会冲突。同时读的频率远大于...
  • 高并发 PV 问题 他的文章标题是这样的: 首先他给出了一个业务场景:在一些需要统计 PV(Page View), 即页面浏览量或点击量高并发系统中,如:知乎文章浏览量,淘宝商品页浏览量等,需要统计相应数据做分析。 ...
  • 高并发下的ArrayList 我们都知道,ArrayList是一个线程不安全的容器。如果在多线程中使用ArrayList,可能会导致程序出错。究竟可能引起哪些问题呢?试看下面的代码: public class ArrayListMultiThread{ static ...
  • 电商中常见的高并发解决方案

    千次阅读 2022-01-17 19:47:29
    本文主要介绍了两种电商项目中常见的高并发解决方案,一种是针对常用并且更新较少的数据做多级缓存,另一种是通过 Nginx 对用户进行限流
  • 极简高并发秒杀商城

    千次阅读 2022-03-18 21:55:04
      这是一款极简高并发秒杀商城项目。本项目偏向于后端。之所以说“极简”,是因为本项目的前端界面没有丰富炫酷的商品界面,目前就只有三个各具特色的商品,只是意思一下,用于充当实际种类繁多的商品。   ...
  • 高并发中的集合有哪些问题

    千次阅读 2022-01-24 16:14:11
    高并发中的集合有哪些问题? JDK1.8的新特性有哪些?
  • 深度学习模型高并发方案

    千次阅读 2022-03-29 17:52:15
    CentOS 下部署Nginx+Gunicorn+Supervisor部署Flask项目 Flask 处理高并发、多线程 Flask 高并发部署方案详细教程! Flask: flask框架是如何实现非阻塞并发的 Flask 高并发部署方案详细教程
  • 规则:每人每天30票(未...高并发页面:投票主页,选手详情页面(含投票活动信息,选手信息,票数,礼物等) 压力并发:单机+单库 (8pvc 16g) QPS<150 公司要求:QPS 3000+,投票时间一个月,不缺钱 优化方案: 一:架构修改 1:数
  • 一、Netty高并发下数据丢失问题分析处理 1、现象 客户端与服务端采用长连接通讯, 传输数据量不大情况下不会出现数据丢失,在大数据量高并发场景下,会出现极少数的数据丢失,存在偶发性。 仔细分析代码处理逻辑,并...
  • Linux操作系统是现在服务器的首选操作系统,在Linux的默认系统参数下,Linux针对高并发的支持性并不是很好。小编从事Linux下应用程序开发多年,关于Linux系统下的高并发,小编自己踩过的坑,及如何解决踩过的坑下面...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,023,332
精华内容 409,332
关键字:

高并发