通常、Web システムのスループット レートは QPS (Query Per Second、1 秒あたりに処理されるリクエストの数) によって測定されます。この指標は、1 秒あたり数万回の同時実行性の高いシナリオを解決するために非常に重要です。たとえば、ビジネス リクエストを処理するための平均応答時間が 100 ミリ秒であると仮定します。同時に、システム内に 20 台の Apache Web サーバーがあり、MaxClients が 500 (Apache 接続の最大数を示す) に設定されているとします。
つまり、私たちの Web システムの理論上のピーク QPS は (理想的な計算方法):
20*500/0.1 = 100000 (100,000 QPS)
え?私たちのシステムは非常に強力なようで、1 秒間に 100,000 件のリクエストを処理できます。5w/s のフラッシュセールは「紙の虎」のようです。もちろん、実際の状況はそれほど理想的ではありません。実際の同時実行性の高いシナリオでは、マシンは高負荷にさらされており、この時点で平均応答時間は大幅に増加します。
Web サーバーに関する限り、Apache が開く接続プロセスが増えるほど、CPU が処理する必要があるコンテキスト スイッチが増え、CPU 消費量が増加し、平均応答時間の増加に直接つながります。したがって、上記の MaxClient の数は、CPU やメモリなどのハードウェア要因に基づいて考慮する必要があります。多いほど良いというわけではありません。 Apache 独自のアベンチを通じてテストし、適切な値を取得できます。次に、メモリ操作レベルでのストレージとして Redis を選択します。同時実行性が高い状態では、ストレージの応答時間が重要になります。ネットワーク帯域幅も要因ですが、このような要求パケットは一般に比較的小さいため、要求のボトルネックになることはほとんどありません。負荷分散がシステムのボトルネックになることはほとんどないため、ここでは説明しません。
次に問題は、私たちのシステムが 5w/s の高い同時実行状態にあると仮定すると、平均応答時間が 100 ミリ秒から 250 ミリ秒に変化する (実際の状況ではさらに多くなります):
20*500/0.25 = 40000 (4) 10,000 QPS)
つまり、1 秒あたり 50,000 のリクエストに直面すると、システムには 40,000 QPS が残ることになります。その差は 10,000 QPS です。
例えば、高速道路の交差点では、1秒間に5台の車が行き来し、高速道路の交差点は通常通り動作します。突然、この交差点は1秒間に4台しか通過できなくなり、交通量は変わらないため、間違いなく渋滞が発生します。 (5レーンが突然4レーンになったような感じです)
同様に、ある秒間では20*500の利用可能な接続プロセスがフル稼働していますが、まだ10,000の新規リクエストがあり、利用可能な接続プロセスが存在しないことが予想されます。システムが異常な状態に陥ります。
実際、同時実行性が高くない通常のビジネス シナリオでも、特定のビジネス リクエスト インターフェイスに問題があり、Web リクエスト全体の応答時間が非常に遅くなることがあります。が非常に長く、Web は徐々に減少し、サーバー上で使用可能な接続の数がいっぱいになり、他の通常のビジネス リクエストに使用できる接続プロセスがなくなりました。
さらに恐ろしい問題は、ユーザーの行動特性です。システムが利用できなくなると、ユーザーがクリックする頻度が高まり、最終的には「雪崩」が発生します (Web マシンの 1 つがハングアップし、トラフィックが停止します)。他の正常に動作しているマシンに分散され、通常のマシンもハングアップし、Web システム全体がダウンするという悪循環が発生します。
3. 再起動と過負荷保護
システムで「雪崩」が発生した場合、むやみにサービスを再起動しても問題は解決しません。最も多い現象は、起動してもすぐにハングアップしてしまうことです。現時点では、イングレス層でトラフィックを拒否してから再起動することをお勧めします。 redis/memcacheなどのサービスもダウンしている場合は、再起動時の「ウォームアップ」に注意が必要で、時間がかかる場合があります。
フラッシュ セールやラッシュ セールのシナリオでは、トラフィックがシステムの準備や想像を超えることがよくあります。このとき、過負荷保護が必要です。リクエストの拒否は、システムのフル負荷状態が検出された場合の保護手段でもあります。フロントエンドでフィルタリングを設定するのが最も簡単な方法ですが、このアプローチはユーザーから「批判」される動作です。より適切なのは、顧客からの直接リクエストを迅速に返すために、CGI エントリー層で過負荷保護を設定することです
高い同時実行下でのデータセキュリティ
複数のスレッドが同じファイルに書き込む場合、「スレッド」は「安全」として表示されることがわかっています。問題 (複数のスレッドが同じコード部分を同時に実行します。各実行の結果が単一スレッドの実行の結果と同じで、結果が期待どおりであれば、スレッドセーフです)。 MySQL データベースの場合は、独自のロック メカニズムを使用して問題を解決できます。ただし、大規模な同時実行シナリオでは、MySQL はお勧めできません。フラッシュ セールやラッシュ セールのシナリオでは、「過剰送信」という別の問題が発生します。この点を慎重に制御しないと、過剰な送信が発生します。一部の電子商取引会社では、購入者が写真撮影に成功した後、販売者が注文が有効であると認識せず、商品の配送を拒否する行為を行っていると聞いています。ここでの問題は、必ずしも販売業者が不正であるということではなく、システムの技術レベルでの過剰発行のリスクによって引き起こされる可能性があります。
1. 過剰な毛の成長の理由
ある急ぎ購入シナリオで、合計 100 個の製品しかなく、最後の瞬間に 99 個の製品を消費し、最後の 1 個だけが残ったとします。このとき、システムは複数のリクエストを同時に送信し、それらのリクエストによって読み取られた商品残高はすべて 99 であり、すべてがこの残高判定を通過し、最終的に過剰発行につながりました。 (記事内で前述したシーンと同じです)
上の図では、同時ユーザー B も「購入に成功」し、さらに 1 人が商品を入手できるようになりました。このシナリオは、同時実行性が高い状況で非常に発生しやすくなります。
最適化計画 1: 在庫フィールド番号フィールドを 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); } ?>
2。解決すべきアイデアはたくさんあります。スレッド セーフティ、から始めることができます。 「悲観的ロック」の方向性が議論され始めました。
悲観的ロック、つまり、データを変更するときに、外部リクエストからの変更を除外するためにロック状態が採用されます。ロック状態になった場合は、待機する必要があります。
上記の解決策はスレッドの安全性の問題を解決しますが、私たちのシナリオは「高い同時実行性」であることを忘れないでください。言い換えれば、そのような変更リクエストが多数あり、各リクエストは「ロック」を待つ必要があるため、一部のスレッドはこの「ロック」を取得する機会がなく、そのようなリクエストはそこで終了します。同時に、そのようなリクエストが多数発生し、システムの平均応答時間が即座に増加します。その結果、使用可能な接続の数が枯渇し、システムが例外に陥ります。
最適化計画 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"); } ?>
3. FIFO キューのアイデア
それでは、上記のシナリオを少し変更して、リクエストをキューに直接入れ、FIFO (First Input First) を使用してみましょう。出力、先入れ先出し)、この場合、一部のリクエストがロックを取得しないことはありません。これを見ると、マルチスレッドを強制的にシングルスレッドにするような感じでしょうか?
これでロックの問題は解決され、すべてのリクエストは「先入れ先出し」キューで処理されます。さらに、同時実行性が高いシナリオでは、リクエストが多数あるため、キュー メモリが瞬時に「爆発」し、システムが再び異常状態に陥る可能性があります。または、巨大なメモリ キューを設計することも解決策です。ただし、システムがキュー内のリクエストを処理する速度は、キューへの異常な流入の数と比較することはできません。つまり、キュー内のリクエストの数はますます蓄積され、最終的には Web システムの平均応答時間は依然として大幅に低下し、システムは依然として例外に陥ってしまいます。
4. ファイルロックの考え方
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); ?>
5. 楽観的ロックのアイデア
この時点で、「楽観的ロック」のアイデアについて議論できます。楽観的ロックは「悲観的ロック」に比べて緩いロック機構を採用しており、その多くはバージョンアップを利用します。実装では、このデータに対するすべてのリクエストが変更可能ですが、データのバージョン番号は一貫したバージョン番号を持つもののみが正常に取得され、その他のリクエストは失敗に返されます。この場合、キューの問題を考慮する必要はありませんが、CPU の計算オーバーヘッドが増加します。ただし、全体的には、これはより良い解決策です。
「楽観的ロック」機能をサポートするソフトウェアやサービスは数多くあり、Redis の watch もその 1 つです。この実装により、データのセキュリティが確保されます。
最適化計画 5: Redis で見る
<?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 class="brush:php;toolbar:false">"; 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 class="brush:php;toolbar:false">"; // 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 class="brush:php;toolbar:false">"; var_dump($mywatchlist); }else{ $redis->hSet("watchkeylist","user_".mt_rand(1, 9999),'meiqiangdao'); echo "手气不好,再抢购!";exit; } } ?>
以上がフラッシュセールのアイデアと高同時実行下でのデータセキュリティを分析するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

MySQLのパフォーマンスを効果的に監視する方法は? MySqladmin、ShowGlobalStatus、PerconAmonitoring and Management(PMM)、MySQL EnterpriseMonitorなどのツールを使用します。 1. mysqladminを使用して、接続の数を表示します。 2。showglobalstatusを使用して、クエリ番号を表示します。 3.PMMは、詳細なパフォーマンスデータとグラフィカルインターフェイスを提供します。 4.mysqlenterprisemonitorは、豊富な監視機能とアラームメカニズムを提供します。

MySQLとSQLServerの違いは次のとおりです。1)MySQLはオープンソースであり、Webおよび埋め込みシステムに適しています。2)SQLServerはMicrosoftの商用製品であり、エンタープライズレベルのアプリケーションに適しています。ストレージエンジン、パフォーマンスの最適化、アプリケーションシナリオの2つには大きな違いがあります。選択するときは、プロジェクトのサイズと将来のスケーラビリティを考慮する必要があります。

高可用性、高度なセキュリティ、優れた統合を必要とするエンタープライズレベルのアプリケーションシナリオでは、MySQLの代わりにSQLServerを選択する必要があります。 1)SQLServerは、高可用性や高度なセキュリティなどのエンタープライズレベルの機能を提供します。 2)VisualStudioやPowerbiなどのMicrosoftエコシステムと密接に統合されています。 3)SQLSERVERは、パフォーマンスの最適化に優れた機能を果たし、メモリが最適化されたテーブルと列ストレージインデックスをサポートします。

mysqlManagesCharacterSetSetSetsAndCollations ByUSINGUTF-8ASTHEDEDEFAULT、CONFIGURATIONATDATABASE、TABLE、ANDCOLUMNLEVELS、ANDREQUIRINGCAREACTERSETANDCOLLATIONSFORADABASE.2

MySQLトリガーは、特定のデータ操作が実行されたときに一連の操作を実行するために使用されるテーブルに関連付けられた自動的に実行されたストアドプロシージャです。 1)定義と機能のトリガー:データ検証、ロギングなどに使用。2)動作原則:それは前後に分割され、行レベルのトリガーをサポートします。 3)使用例:給与の変更を記録したり、在庫を更新したりするために使用できます。 4)デバッグスキル:ShowTriggersとShowCreatetriggerコマンドを使用します。 5)パフォーマンスの最適化:複雑な操作を避け、インデックスを使用し、トランザクションを管理します。

MySQLでユーザーアカウントを作成および管理する手順は次のとおりです。1。ユーザーの作成:createUser'newuser '@' localhost'identifidedby'password 'を使用します。 2。許可を割り当てる:grantselect、insert、updateonmydatabase.to'newuser'@'localhost 'を使用します。 3.許可エラーを修正:Revokeallprivilegesonmydatabase.from'newuser'@'localhost 'を使用します。次に、許可を再割り当てします。 4。最適化権限:Showgraを使用します

MySQLは、迅速な開発や中小規模のアプリケーションに適していますが、Oracleは大規模な企業や高可用性のニーズに適しています。 1)MySQLはオープンソースで使いやすく、Webアプリケーションや中小企業に適しています。 2)Oracleは強力で、大企業や政府機関に適しています。 3)MySQLはさまざまなストレージエンジンをサポートし、Oracleは豊富なエンタープライズレベルの機能を提供します。

他のリレーショナルデータベースと比較したMySQLの欠点には次のものがあります。1。パフォーマンスの問題:大規模なデータを処理する際にボトルネックに遭遇する可能性があり、PostgreSQLは複雑なクエリとビッグデータ処理でより良いパフォーマンスを発揮します。 2。スケーラビリティ:水平スケーリング能力は、Google SpannerやAmazon Auroraほど良くありません。 3。機能的な制限:高度な機能におけるPostgreSQLやOracleほど良くないため、一部の関数では、より多くのカスタムコードとメンテナンスが必要です。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

VSCode Windows 64 ビットのダウンロード
Microsoft によって発売された無料で強力な IDE エディター

MinGW - Minimalist GNU for Windows
このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

mPDF
mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

PhpStorm Mac バージョン
最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

SublimeText3 英語版
推奨: Win バージョン、コードプロンプトをサポート!
