実際のプロジェクトで php+redis を使用して HTTP 500: Internal Server Error をトラブルシューティングする方法

墨辰丷
リリース: 2023-03-28 08:08:01
オリジナル
1833 人が閲覧しました

ユーザー数は急速に増加し、アクセス数は短期間で 2 倍になりました。初期のキャパシティ プランニングは比較的良好であったため、ハードウェア リソースはそれをサポートできましたが、ソフトウェア システムには大きな問題がありました。リクエストの 40% が HTTP 500: Internal Server Error を返します

問題の説明
初期の適切な容量計画により、ユーザー数は急速に増加し、アクセス数は短期間で 2 倍になりました。 、ハードウェア リソースはサポートできますが、ソフトウェア システムに大きな問題があります:
リクエストの 40% が Return HTTP 500: Internal Server Error になります
ログを確認すると、接続処理でエラーが発生していることがわかりましたPHP の <->
デバッグ処理

初回
最初は根本原因が見つからなかったので、次のようなエラー関連のさまざまな方法を試すことができます:
PHP の数を増やす接続を増やし、タイムアウトを500ミリ秒から2.5秒に増やします
PHP設定でdefault_socket_timeoutを無効にします
ホストシステムでSYNクッキーを無効にします
RedisとWebサーバーを確認しますファイル記述子の数を確認します
ホストシステムのmbufferを増やします
TCPバックログの数を調整します
...

多くの方法を試しましたが、どれも効果がありませんでした

2回目
この問題をプレリリース環境で再現したいと考えましたが、残念ながら、おそらくトラフィックが再現できるほど大きくないため、まだ失敗しました

3 回目
コード内で Redis 接続が閉じられていない可能性がありますか?
通常、PHP は実行終了時にリソース接続を自動的に閉じますが、古いバージョンではメモリ リークが発生する可能性があるため、安全を期すためにコードを変更して接続を手動で閉じます
結果はまだ無効です

4回目
不審なターゲット: phpredisクライアントライブラリ
A/Bテストを実施し、predisライブラリを置き換え、データセンター内のユーザーの20%に導入
適切なコード構造のおかげで置き換え作業が完了すぐに結果が得られます まだ無効ですが、良い面もあります 5回目

Redisのバージョンを確認したところ、その時点での最新バージョンでした。は v2.8.9 でした

Redis をアップグレードして試してみてください。アップグレード後もまだ動作しません 大丈夫、楽観視してください。これは Redis バージョンを最新にアップグレードする方法ではありません

6 回目です

たくさんのドキュメントを検索したところ、公式ドキュメントで適切なデバッグ方法を見つけました。 Redis Software Watchdog を開いた後に実行します:

$ redis-cli --latency -p 6380 -h 1.2.3.4
min: 0, max: 463, avg: 2.03 (19443 samples)
ログイン後にコピー

Redis ログを表示します:

...
[20398] 22 May 09:20:55.351 * 10000 changes in 60 seconds. Saving...
[20398] 22 May 09:20:55.759 * Background saving started by pid 41941
[41941] 22 May 09:22:48.197 * DB saved on disk
[20398] 22 May 09:22:49.321 * Background saving terminated with success
[20398] 22 May 09:25:23.299 * 10000 changes in 60 seconds. Saving...
[20398] 22 May 09:25:23.644 * Background saving started by pid 42027
...
ログイン後にコピー

問題を見つけました:

データを保存数分ごとにハードディスクにアクセスしているのに、バックグラウンド ストレージをフォークするのになぜ約 400 ミリ秒かかるのですか (上記のログで 1 番目と 2 番目のエントリの時間を確認できます)

この時点で、ついにソースを見つけました。問題: Redis インスタンスには大量のデータがあるため、永続化操作ごとにバックグラウンド プロセスをフォークするのに非常に時間がかかり、業務内でキーが頻繁に変更されるため、永続化が頻繁にトリガーされます。解決策: 永続化には別のスレーブを使用します。このスレーブは実際のトラフィック リクエストを処理しません。唯一の機能は、以前の Redis インスタンスの永続化操作をこのスレーブに転送することです。明らかに、問題は基本的に解決されていますが、時々エラーが報告されます


7 回目

考えられるトラブルシューティング Redis の遅いクエリをブロックすると、キー * がどこかで使用されていることがわかります。 Redis では、このコマンドは当然深刻なブロックを引き起こします。

前回の調整後、トラフィックが増加し続けた場合でも、問題は解決されました。 、それは耐えることができました

しかし、彼らは新しい問題に気づきました:

現在の方法では、リクエストが来たときにRedis接続を作成し、いくつかのコマンドを実行してから、リクエストの量が多い場合、この方法では切断されます。コマンドの半分以上が接続操作の処理に使用されており、ビジネス ロジックの処理を超えて Redis の速度が低下します 解決策: プロキシを導入し、twitter の twemproxy を選択しました。プロキシをインストールするだけで済みます。各 Web サーバーでは、twemproxy が Redis インスタンスとの永続的な接続を担当し、これにより接続操作が大幅に削減されます

twemproxy にも 2 つの便利な場所があります:

memcached をサポート

キーなどの非常に時間のかかる、または危険なコマンドをブロックできます。フラッシュオール

効果は当然完璧で、以前の接続エラーを心配する必要はもうありません


9回目

データシャーディングを渡して最適化を継続します:

異なるコンテキストでデータを分割して分離します

同じデータの一貫したハッシュシャーディングcontext

効果:

各マシンのリクエストと負荷を削減します

キャッシュの信頼性を向上させます 安全性、ノード障害を心配する必要はありません

以上がこの記事の全内容です、皆さんの学習に役立つことを願っています。

関連する推奨事項:

PHP で

redis に存在しない 6 桁の乱数を取得するメソッド

メソッド


redisWeiboメソッドを公開するメッセージキューのPHP実装

CIフレームワーク(CodeIgniter)の操作redisステップ分析

以上が実際のプロジェクトで php+redis を使用して HTTP 500: Internal Server Error をトラブルシューティングする方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート