プロゞェクトの生涯から1幎



この蚘事では、プロゞェクトAnswersに関連するタスクの実装で遭遇したすべおの困難ず萜ずし穎を思い出しお説明し、プロゞェクトのアヌキテクチャに぀いおも説明したす。

それはすべお、私の契玄が終了したずいう事実から始たりたしたMail.ruメヌルの䜜業に参加した幎の間に。 「冒険は再び私を埅っおいたす」、「新しい囜、新しい仕事」ず私の考えをフラッシュしたした。 私は䞊叞のもずに行きたしたが、それでも議論の過皋で、面癜いプロゞェクトの圢で冒険の䞀郚を受け取りたした-応答プロゞェクトを取り䞊げたす。

2012幎10月15日の時点で、プロゞェクトには1日あたり平均350䞇人のナニヌクビゞタヌが蚪れたした。
カりントは、各蚪問者に発行される䞀意の「Cookie」Cookieによっお実行されたした。 蚪問者のブラりザでCookieの受信が無効になっおいる堎合、蚪問者はカりントされたせん。
プロゞェクトの名刺はスクリヌンず呌ばれるこずもありたす。スクリヌンは誰もが知っおいるず思いたす。



䜿甚されたテクノロゞヌのセットは次のずおりです。

アヌキテクチャ

名行き先CPUラム、GBhddメモ
プリムス正面2xE550482 x sata゚ントリヌポむント、バランサヌ
アルファベック2xXeon叀い22 x scsiその䞊で、すべおのクラりンスクリプトを起動したす
アルゎンベック2xE550482 x sata
ブタンベック2x E550642 x sata
ルナベック2xE540582 x sataここでwapずmバヌゞョン
オクタンベック2xE540582 x sata
メタンベック2xE550642 x sata
プロパンベック2xE540542 x sata
ラドンベック2xE550482 x sata
ネオンベック2xE5-2620162 x sata新しい
窒玠ベック2xE5-2620162 x sata新しい
プラズマベック2xE5-2620162 x sata新しい
タむタン拠点2 x E5620964sata + 20sasマスタヌ
ブラン拠点2 x E5620642 sata + 4 ssd䞀次レプリカ
極倧拠点2 x 5110322 sata + 4 scsi管理パネルのレプリカ
ミニマス拠点2 x 5110162 sata + 4 scsi管理パネルのレプリカ
巚人拠点2 x 513086 scsiコメントベヌス
問題は次のずおりです。
リヌダヌシップからの挑戊
サヌビスの安定した運甚ずそのさらなる開発の可胜性、特にモバむル版の起動を確認しおください。
Mysqlに移行しおプロセスロゞックをグロヌブに入れるず、ほずんどの問題が解決したす。

最初のステップは監芖でした。 私は圌に぀いお蚘事に曞きたしたずころで、
AnyEventで曞き盎したずころ、生産性は毎秒50から24䞇行に増加したした。

圌は次のこずに目を開けたした。
  1. 私たちは毎日萜ちたす
  2. ゚ラヌ504の膚倧な背景、1日玄5䞇。

504の理由は䜕ですか

Yandexからの手玙
otvet.mail.ruに぀いおは、負荷を増やし始めたしたが、1分あたり200を超えるリク゚ストを行うこずはしたせんでした
時刻に関係なくHTTP 503を受信し始めるず刀明したす。 可胜ですか
あなたの偎でそれを排陀したすか
別の問題が衚面化したした。バランサヌでは、1぀のIPから1秒あたり1぀のリク゚ストの制限があり、それを増やすず負荷に察凊できなくなりたす。

怜玢トラフィックはResponsesプロゞェクトにずっお最も重芁なこずなので、迅速に行動する必芁がありたす。 誰もが緊匵しおいお、状況は過熱しおいたす=。

最も単玔で、最も簡単で、安䟡なものから、ネオン、プラズマ、窒玠の3぀のバック゚ンドを賌入したした。 プリムスバランサヌにRAMを远加したした、蚱可されおいないすべおのナヌザヌ向けにnginxに玄40のhtmlキャッシュを远加したした。 バランサヌの制限は、1秒あたり15リク゚ストに増加したした。

圌らは毎日萜䞋を止め、Yandexはもはや私たちに぀いお䞍平を蚀いたせんでした。 重倧な問題が解決されたので、タスクに぀いお考えるこずができたす。

今埌は、新しいAPIで、遅いHTMLの問題が解決されたず蚀いたす。 独自の解析枈みPerl XSパヌサヌを適甚し、デヌタベヌスに保存するずきにのみ解析したした。 誰かがXSSを芋぀けるず、すべおの文字を解析するのに倚くの時間5ペタバむトのデヌタがかかるため、そのような゜リュヌションはメヌルには適しおいたせん。そのため、保護を远加し、その堎で解析するのがより簡単で迅速です。

移行ずモバむル版

移行は、デヌタの敎合性の維持ずプロゞェクトの24時間365日のパフォヌマンスずいう2぀の条件を満たす必芁がありたす。 したがっお、プロゞェクトをオフにしおデヌタを転送するず倱敗したす。

APIを䜜成したす。これに基づいお、モバむルバヌゞョンず将来の「ビッグ」バヌゞョンの䞡方で、すべおが機胜したす。 APIはマッスルからのみ読み取り、叀いデヌタベヌスず新しいデヌタベヌスの䞡方に曞き蟌みたす。

MySQLが叀いデヌタベヌスから倉曎を取埗するために、同期する必芁がある゚ンティティを曞き蟌むキュヌを開始したしょう叀い゚ンティティから取埗しお、新しい゚ンティティで远加たたは眮換したす。

これを行うには、ベヌス党䜓を゚ンティティに分割する必芁がありたす。 たずえば、回答、質問、ナヌザヌ、すべおのナヌザヌの回答などを再同期するタスク。

たた、同期のためのタスクのストリヌムが膚倧であるため、このキュヌのハンドラヌが䞊行しお動䜜するこずを考慮する必芁がありたす。 最終的に12個のフォヌクを凊理できたした。

これはすべお必芁なため、い぀でもキュヌにタスクを远加しお、必芁な゚ンティティを完党に再同期できたす。

それで、それは始たりたした。 1月10日、 アレックスQ倧麊がリリヌスされたした。 ラむンは筋肉に実装されたした。 マッスル甚に2぀のサヌバヌ「バヌチ」ず「パむン」ず呌ばれるず2぀のフロント「バロン」ず「バヌボン」を賌入したした。 マッスルマスタヌずレプリカ。 圌らは叀いバヌゞョンに、再同期のためにキュヌにタスクを曞くこずを教えたした。 それは非垞に日垞的で、痛みを䌎う長いプロセスでした。 叀いグロヌブに曞き蟌む小さなグロヌブのすべおの堎所を芋぀けお、察応する再同期タスクでバックアップする必芁がありたした。

珟時点では、䞻なこずは次のこずを忘れないこずです。

䞊蚘の゚ラヌはそれぞれ14日間かかりたす。 なぜそんなに倚いのですか これに぀いおは埌で詳しく説明したす。

そのため、叀いバヌゞョンはキュヌに曞き蟌み、負荷を確認できたす。 叀いバヌゞョンを最初に2぀のベックで展開し、次に4぀のベックで展開し、筋肉を確認したす。すべお問題ありたせん。すべおの分岐で展開し、負荷を維持したす。 次のステップに進みたす。

圌らは、子を分岐しお远跡する方法を知っおいるキュヌハンドラを䜜成したした。子が萜ちたら、新しい子を生成したす。 圌はタスクの䞀郚を取り、それらを再同期し、それらを必芁な構造に倉えたす。 将来的には、2぀の戊略のうち、それぞれがあらゆる皮類のタスクをレむクする12のフォヌクの起動が、タスクAを実行する4぀のフォヌク、タスクBを完了する4぀のフォヌクの起動よりも遅いこずに気付きたした。

これは、キュヌプロセッサが珟圚のパスで再同期した゚ンティティを蚘憶し、再床䞀臎する堎合はそれらをスキップするずいう事実によっお説明されたす。たた、゚ンティティの皮類を制限するず、既に凊理されたタスクに入る確率がはるかに高くなりたす。

その結果、キュヌに曞き蟌むように叀いバヌゞョンを教えたした。キュヌプロセッサは準備ができおいたす。 叀いバヌゞョンが戊闘に投入されたす。 キュヌは山積みになっおいたすが、これたでのずころはレむクされおいたせん。

次に、すでに蓄積されたデヌタをあるデヌタベヌスから別のデヌタベヌスに転送する必芁がありたす。 箄500ギガバむトです。 どうやっおやるの ありがずうアレックスQ =

チャレンゞ
叀いSQLデヌタベヌスからMySQLぞの倧きなテヌブル最倧1億5千䞇レコヌドの移行。 同時に、構造はわずかに倉曎できたす。たずえば、叀いSQLデヌタベヌスでは、ブヌル型フィヌルドはCHAR1でした非衚瀺には倀 ''たたは 'H'を䜿甚できたす。MySQLではTINYINTになりたす非衚瀺は0たたは1になりたす。
デヌタ転送に加えお、叀いデヌタベヌスでデヌタを远加および倉曎できたす。 この問題は、叀いデヌタベヌスのどのデヌタが倉曎たたは远加されたかに぀いおの情報が曞き蟌たれるキュヌを䜜成するこずで解決されたす。 テヌブルの移行䞭、「事前同期」のゞョブはキュヌに蓄積されたす。 その埌、キュヌは別のスクリプトで解析されたす。

移行
  1. INSERTを䜿甚するよりもはるかに高速であるため、文字列の1000デフォルトでは、スタヌトアップキヌによっおオヌバヌラむドされるのパックでLOAD DATA INFILEを介しおMySQLにむンポヌトしたす。
  2. FIFOパむプをデヌタ転送ファむルずしお䜿甚したす。これは、すべおのデヌタがディスクに曞き蟌たずにメモリを通過するためです。 ファむルを䜿甚するよりも倧幅に高速になりたす。
  3. このスクリプトは、叀いSQLデヌタベヌスたずえば、10000からN行を読み取りたす。
  4. スクリプトは子プロセスを解析したす。 このプロセスでは、読み取り甚のFIFOが開かれ、そこからMySQLでLOAD DATA INFILEが実行されたす。
  5. 芪はfifoにK行たずえば1000を曞き蟌みたす。 各パックの埌、パむプのファむルハンドルを閉じ、子プロセスが終了するたで埅機し、ステップ1で取埗したデヌタがなくなるたでステップ2から繰り返したす。

2013幎2月26日-最初のコミット。 2013幎3月6日たでに、䜜業バヌゞョンが準備できたす。 着信テヌブル叀いSQLデヌタベヌスず出力テヌブルMySQLold_to_MySQLの説明を取埗する関数を䜜成し、すべおの凊理を実行したした。 突然のfakap䞭にれロから開始しないように、old_migrate MySQLテヌブルに各テヌブルの最埌に移行された行のIDを保存したす。

LOAD INFILE IGNOREではなくLOAD INFILE REPLACEを䜿甚しおいるため、fakapから回埩するずきに、叀いSQLデヌタベヌスのデヌタ倉曎が倱われるこずはありたせん。

3月15日、デフォルト倀の問題は䞀時的に解決されたした。叀いSQLデヌタベヌスからNULLが発生し、MySQLのNOT NULL DEFAULT列が0の堎合、NULLを挿入しようずするずクラッシュしたす。 スキヌムの説明には、必芁なキヌ列のセットがありたす。残りはすべお、NULLが来た堎合にDEFAULTを挿入したす。

3月20日、SIGPIPEずの戊争が始たりたした。

戊争の段階
シグシプ戊争は、11月13日ず14日に2日間続きたした。 ずおも忙しい2日間でした。

合蚈で、これらの500ギガバむトを転送するのに14日かかりたした。

転送の進行䞭、新しいAPIのアルファ版Perl、fast_cgiは既に準備されおいたした。

デヌタを転送し、䌁業ナヌザヌ向けのテストモバむルバヌゞョンを開始したした。 芋お、テストしたす。 偶然、叀いバヌゞョンのログで、背䞭の1぀で、小さなperjochkaがDBDモゞュヌルがないこずを誓うずいう゚ラヌに気付きたした。 これは、前からのゞョブがキュヌを離れおおらず、ベヌスが䞀貫しおいないこずを意味したす。 ああ、ク゜ 私はすべおを再び転送しなければなりたせんでした。 14日が経過したした=。

これで、デヌタ転送埌、キュヌのレむクを開始でき、玄3億の巚倧なゞョブが蓄積されたした。

ハンドラヌの開始-遅すぎる。 私たちはブレヌキの原因を探しおいたしたが、タヌンしたプレヌトのむンデックスが必芁であるこずがわかりたした。 私は本圓に14日間再び埅ちたくありたせんでした。 別の同じプレヌトを䜜成したしたが、むンデックスがありたす。 圌女たちは叀いバヌゞョンを公開し、圌女はむンデックス付きの新しい版に曞いた。 それはInnoDBでした。 むンデックスを远加したした。 圌らはタブレットをかき集めお殺したした。 すべおの名前を元に戻したした。

うたくいくようです。 どうぞ

新しいAPIは、䞡方のデヌタベヌスに曞き蟌むこずができる必芁がありたす。 あたりにも倚くの時間を埅たないように非同期に曞き蟌みたす。 これを行うには、新しいデヌタベヌスのテヌブルで、自動むンクリメントの初期䜍眮を䜿甚しおidで予玄したす。 たずえば、叀いデヌタベヌスでは質問の最倧IDは1000で、新しいデヌタベヌスの同様のテヌブルでは、自動むンクリメント2000の初期䜍眮を蚭定したす。

新しいAPIを䜿甚しお質問を远加し、識別子2001を芋぀け、叀いデヌタベヌスに远加し、そこに識別子1001を远加し、識別子2001でレコヌドを曎新し、識別子1001でレコヌドに倉換したす。したがっお、゚ンティティの識別子はデヌタベヌスで䞀臎したす。
その埌、マッスルを再起動するか、テヌブルを倉曎した埌、自動むンクリメントがプラむマリキヌの最倧倀にリセットされるこずを孊びたした。 したがっお、これを回避するために、自動むンクリメントの開始番号に等しい倧きな識別子を持぀゚ンティティデヌタベヌスをMySQLに远加したした。
必芁な゚ンティティを再同期するためのタスクをキュヌに远加するこずにより、さらにすべおのphakapsが解決されたした。

私はもう少し思い出したした運甚郚門から、どういうわけか、デヌタセンタヌの1぀を完枈しなければならないかもしれないずいうニュヌスを聞きたした。モバむルバヌゞョンはすでに戊い䞭であり、叀いデヌタベヌスを持぀サヌバヌがこのデヌタセンタヌにあるずいう事実を考えるず、別の新しいMySQLデヌタベヌス-それは完党に悲しくなりたした。 しかし、幞いなこずに、予枬は実珟したせんでした。

䜕が起こったのか想像しおみおください。

デヌタセンタヌに叀いデヌタベヌスを返枈したした-その埌、すぐに別のデヌタセンタヌの前面を䞞くしこのニュヌスを知ったずきすぐにそれを行いたした、モバむルバヌゞョンを読み取り専甚モヌドに切り替え、党員をモバむルバヌゞョンにリダむレクトしたす。

デヌタセンタヌに新しいデヌタベヌスを返枈したした-同期のためにキュヌの蚘録をオフにしたす。 デヌタセンタヌが機胜し始めた埌、問題の発生埌に䜜成されたすべおの゚ンティティをキュヌに入れ、静かに再同期したす。

3月、モバむル版が発売されたした。 1日玄50䞇人のナニヌクな人々がそこに来たした。 負荷を抑え、すべおがスマヌトに機胜したす。

プロゞェクトのアヌキテクチャは次の圢匏を取りたした。
名行き先CPUラム、GBhddメモ
男爵正面2xE5-2620322 x satahttpd + mod_fcgid、倧きな電力マヌゞン
バヌボン正面2xE5-2620322 x satahttpd + mod_fcgid、倧きな電力マヌゞン
ベレザ拠点2xE5-2609962 x SATA + 10 x ssdmysqlマスタヌ
゜スナ拠点2xE5-2609962 x SATA + 10 x ssdmysqlレプリカ
ピフタ拠点2xE5-2609962 x SATA + 10 x ssdmysqlレプリカ
荷銬車メンケシュ2xE5-2620642 x sata2぀のmemcachedむンスタンス
怜玢゚ンゞンずJSが無効になっおいる人向けのサヌバヌバヌゞョンの䜜成を開始したした。

圌らはそれをし、モスクワ地方に巻き蟌んだ。 1秒あたり800リク゚ストの負荷で、Apacheが燃えおいるこずがわかりたした。 最初はmod_fcgidに疑念がありたしたが、犯人はmod_rpafであるこずが刀明したした。 Monsのおかげで、圌はApache Apacheクラストを巧みにプレむしたした。

圌らはmod_rpafを攟棄し、nginxを䜿甚しおX-Real-IPヘッダヌからIPを投げたした。

圌らはロシア䞭にそれを転がしたした、我々は負荷を保ちたす。 圌らは新しい「ビッグ」バヌゞョンを䜜成し、党員をリダむレクトし始めたした。 11月19日、叀いバヌゞョンは終了したした。

プリムスバランサヌの地獄の制限を削陀したした1぀のIPから毎秒15リク゚スト。 負荷を通垞に保ちたす。 APIからの1秒あたり玄950リク゚スト。

出垭者は1日あたり平均650䞇人です。

すべおのサヌバヌでCentOS 64ビットを䜿甚し、RPMパッケヌゞを介しお戊闘ぞの展開が行われたす。 珟時点では、perlachkaはただApache2mod_fcgidの䞋で回転しおいたす。 yumがバッグをロヌルバックした埌、ベックを順番に再起動したす。

前面では、次のものを䜿甚したす。
proxy_next_upstream timeout error http_502 http_504;

぀たり、ナヌザヌが502たたは504を受け取った堎合、ナヌザヌは別のバック゚ンドの䜿甚を蚱可されるため、Apacheの再起動による䞍快感が最小限に抑えられたす。

負荷チャヌトはこちらにありたす 。

このメモが、私たちが歩いたレヌキを螏たないようにするのに圹立぀こずを願っおいたす 芚えおおいおください、あなた自身からよりも他人の間違いから孊ぶ方が良いです :)

Source: https://habr.com/ru/post/J214919/


All Articles