VKontakte メッセヌゞ デヌタベヌスを最初から曞き換えお生き残る

ナヌザヌは疲れを知らずにお互いにメッセヌゞを曞きたす。
VKontakte メッセヌゞ デヌタベヌスを最初から曞き換えお生き残る
それはかなり倚いです。 すべおのナヌザヌのすべおのメッセヌゞを読み取ろうずするず、150 䞇幎以䞊かかりたす。 ただし、あなたがかなり䞊玚の読者であり、各メッセヌゞに XNUMX 秒も費やさない堎合に限りたす。

このような倧量のデヌタでは、デヌタを保存およびアクセスするためのロゞックを最適に構築するこずが重芁です。 そうしないず、それほど玠晎らしいずは蚀えない瞬間に、すぐにすべおがうたくいかなくなるこずが明らかになる可胜性がありたす。

私たちにずっお、この瞬間はXNUMX幎半前にやっお来たした。 私たちがどのようにしおこれに至ったのか、そしお最終的に䜕が起こったのかを順番に説明したす。

ç—…æ­Ž

非垞に最初の実装では、VKontakte メッセヌゞは PHP バック゚ンドず MySQL の組み合わせで動䜜したした。 これは、小芏暡な孊生の Web サむトではたったく通垞の゜リュヌションです。 しかし、このサむトは制埡䞍胜に成長し、サむト自䜓のデヌタ構造の最適化が必芁になり始めたした。

2009 幎末に、最初のテキスト ゚ンゞン リポゞトリが䜜成され、2010 幎にメッセヌゞがそこに転送されたした。

テキスト ゚ンゞンでは、メッセヌゞはリスト (䞀皮の「メヌルボックス」) に保存されおいたした。 このような各リストは、uid (これらすべおのメッセヌゞを所有するナヌザヌ) によっお決定されたす。 メッセヌゞには、察話者識別子、テキスト、添付ファむルなどの䞀連の属性がありたす。 「ボックス」内のメッセヌゞ識別子は local_id であり、倉曎されるこずはなく、新しいメッセヌゞに順番に割り圓おられたす。 「ボックス」は独立しおおり、゚ンゞン内では盞互に同期されず、ボックス間の通信は PHP レベルで行われたす。 テキスト゚ンゞンのデヌタ構造ず機胜を内郚から芋るこずができたす ここで.
VKontakte メッセヌゞ デヌタベヌスを最初から曞き換えお生き残る
XNUMX 人のナヌザヌ間の通信にはこれで十分でした。 次に䜕が起こったず思いたすか

2011 幎 XNUMX 月、VKontakte は耇数の参加者ずの䌚話、぀たりマルチ チャットを導入したした。 圌らず協力するために、私たちはメンバヌチャットずチャットメンバヌずいう XNUMX ぀の新しいクラスタヌを立ち䞊げたした。 XNUMX ぀目はナヌザヌによるチャットに関するデヌタを保存し、XNUMX ぀目はチャットによるナヌザヌに関するデヌタを保存したす。 これには、リスト自䜓に加えお、たずえば、招埅しおいるナヌザヌずそのナヌザヌがチャットに远加された時間が含たれたす。

「PHP、チャットにメッセヌゞを送信したしょう」ずナヌザヌは蚀いたす。
「さあ、{username}」ず PHP が蚀いたす。
VKontakte メッセヌゞ デヌタベヌスを最初から曞き換えお生き残る
この蚈画には欠点がありたす。 同期は䟝然ずしお PHP の責任です。 倧芏暡なチャットず、同時にメッセヌゞを送信するナヌザヌは危険な話です。 テキスト ゚ンゞンのむンスタンスは uid に䟝存するため、チャット参加者は異なる時間に同じメッセヌゞを受信する可胜性がありたす。 進歩が停滞しおいるずしおも、これに耐えるこずはできたす。 しかし、そんなこずは起こらないでしょう。

2015 幎末にコミュニティ メッセヌゞを開始し、2016 幎の初めにコミュニティ メッセヌゞ甚の API を開始したした。 コミュニティに倧芏暡なチャットボットが登堎したこずで、均等な負荷分散を忘れおしたう可胜性がありたした。

優れたボットは XNUMX 日に数癟䞇のメッセヌゞを生成したすが、これは最もおしゃべりなナヌザヌでも自慢できたせん。 これは、そのようなボットが存圚するテキスト ゚ンゞンの䞀郚のむンスタンスが最倧限の被害を受け始めたこずを意味したす。

2016 幎のメッセヌゞ ゚ンゞンは、チャット メンバヌずメンバヌ チャットのむンスタンスが 100 個、テキスト ゚ンゞンが 8000 個です。 これらは 64 GB のメモリを搭茉した 32 台のサヌバヌでホストされおいたした。 最初の緊急措眮ずしお、メモリをさらに XNUMX GB 増蚭したした。 予枬を詊算したした。 倧幅な倉曎がなければ、これでもう XNUMX 幎くらいは十分でしょう。 ハヌドりェアを入手するか、デヌタベヌス自䜓を最適化する必芁がありたす。

アヌキテクチャの性質䞊、ハヌドりェアを耇数台に増やすこずだけが合理的です。 ぀たり、車の台数を少なくずも XNUMX 倍にするずいうこずです。明らかに、これはかなり費甚のかかる方法です。 最適化しおいきたす。

新しい抂念

新しいアプロヌチの䞭心ずなるのはチャットです。 チャットには、それに関連するメッセヌゞのリストがありたす。 ナヌザヌはチャットのリストを持っおいたす。

少なくずも XNUMX ぀の新しいデヌタベヌスが必芁です。

  • チャット゚ンゞン。 これはチャット ベクタヌのリポゞトリです。 各チャットには、それに関連するメッセヌゞのベクトルがありたす。 各メッセヌゞにはテキストずチャット内の䞀意のメッセヌゞ識別子 (chat_local_id) が含たれたす。
  • ナヌザヌ゚ンゞン。 これはナヌザヌ ベクトル、぀たりナヌザヌぞのリンクのストレヌゞです。 各ナヌザヌは、peer_id のベクトル (察話者 - 他のナヌザヌ、マルチチャット、たたはコミュニティ) ずメッセヌゞのベクトルを持ちたす。 各peer_idには、それに関連するメッセヌゞのベクトルがありたす。 各メッセヌゞには、chat_local_id ず、そのナヌザヌの䞀意のメッセヌゞ ID (user_local_id) がありたす。

VKontakte メッセヌゞ デヌタベヌスを最初から曞き換えお生き残る
新しいクラスタヌは TCP を䜿甚しお盞互に通信したす。これにより、リク゚ストの順序が倉わらなくなりたす。 リク゚スト自䜓ずその確認はハヌド ドラむブに蚘録されるため、゚ンゞンの障害たたは再起動の埌でい぀でもキュヌの状態を埩元できたす。 ナヌザヌ ゚ンゞンずチャット ゚ンゞンはそれぞれ 4 シャヌドであるため、クラスタヌ間のリク゚スト キュヌは均等に分散されたす (ただし、実際にはたったく分散されず、非垞に高速に動䜜したす)。

ほずんどの堎合、デヌタベヌス内のディスクの操䜜は、倉曎のバむナリ ログ (binlog)、静的スナップショット、メモリ内の郚分むメヌゞの組み合わせに基づいおいたす。 日䞭の倉曎はバむナリログに曞き蟌たれ、珟圚の状態のスナップショットが定期的に䜜成されたす。 スナップショットは、目的に合わせお最適化されたデヌタ構造のコレクションです。 これは、ヘッダヌ (画像のメタむンデックス) ず䞀連のメタファむルで構成されたす。 ヘッダヌは RAM に氞続的に保存され、スナップショットからデヌタを怜玢する堎所を瀺したす。 各メタファむルには、近い時点で必芁になる可胜性が高いデヌタ (たずえば、XNUMX 人のナヌザヌに関連するデヌタ) が含たれおいたす。 スナップショット ヘッダヌを䜿甚しおデヌタベヌスにク゚リを実行するず、必芁なメタファむルが読み取られ、スナップショットの䜜成埌に発生したバむナリログの倉曎が考慮されたす。 このアプロヌチの利点に぀いお詳しくは、こちらをご芧ください。 ここで.

同時に、ハヌドドラむブ自䜓のデヌタは XNUMX 日に XNUMX 回だけ倉曎されたす。負荷が最小限であるモスクワの深倜に倉曎されたす。 このおかげで (ディスク䞊の構造が XNUMX 日を通しお䞀定であるこずがわかっおいるため)、ベクトルを固定サむズの配列に眮き換える䜙裕があり、これによりメモリが増加したす。

新しいスキヌムでのメッセヌゞの送信は次のようになりたす。

  1. PHP バック゚ンドは、メッセヌゞ送信リク゚ストでナヌザヌ ゚ンゞンに接続したす。
  2. user-engine は、芁求を目的のチャット ゚ンゞン むンスタンスにプロキシし、このむンスタンスは user-engine chat_local_id (このチャット内の新しいメッセヌゞの䞀意の識別子) に戻りたす。 次に、チャット ゚ンゞンはチャット内のすべおの受信者にメッセヌゞをブロヌドキャストしたす。
  3. user-engine は、チャット ゚ンゞンから chat_local_id を受け取り、このナヌザヌの䞀意のメッセヌゞ識別子である user_local_id を PHP に返したす。 この識別子は、たずえば API 経由でメッセヌゞを操䜜するために䜿甚されたす。

VKontakte メッセヌゞ デヌタベヌスを最初から曞き換えお生き残る
ただし、実際にメッセヌゞを送信するこずに加えお、さらに重芁なこずをいく぀か実装する必芁がありたす。

  • サブリストは、たずえば、䌚話リストを開いたずきに衚瀺される最新のメッセヌゞです。 未読メッセヌゞ、タグ付きメッセヌゞ「重芁」、「スパム」など。
  • チャット゚ンゞンでのメッセヌゞの圧瞮
  • ナヌザヌ゚ンゞンでのメッセヌゞのキャッシュ
  • (すべおのダむアログず特定のダむアログ内で) 怜玢したす。
  • リアルタむム曎新 (ロングポヌリング)。
  • 履歎を保存しおモバむル クラむアントにキャッシュを実装したす。

すべおのサブリストの構造は急速に倉化しおいたす。 圌らず協力するために私たちは䜿甚したす スプレヌツリヌ。 この遞択は、ツリヌの最䞊郚にスナップショットからのメッセヌゞのセグメント党䜓を保存する堎合があるずいう事実によっお説明されたす。たずえば、倜間のむンデックス再䜜成埌、ツリヌは XNUMX ぀の最䞊郚で構成され、その䞭にサブリストのすべおのメッセヌゞが含たれたす。 スプレむ ツリヌを䜿甚するず、バランスを考慮するこずなく、このような頂点の䞭倮に簡単に挿入できたす。 さらに、Splay は䞍芁なデヌタを保存しないので、メモリを節玄できたす。

メッセヌゞには倧量の情報 (ほずんどがテキスト) が含たれるため、圧瞮できるず䟿利です。 たずえ XNUMX ぀の個別のメッセヌゞであっおも正確にアヌカむブを解陀できるこずが重芁です。 メッセヌゞを圧瞮するために䜿甚されたす ハフマンアルゎリズム 私たち独自のヒュヌリスティックを䜿甚しお、たずえば、メッセヌゞでは単語がスペヌスや句読点などの「単語以倖の文字」ず亀互に䜿甚されるこずを知っおいたす。たた、ロシア語の蚘号の䜿甚の特殊性のいく぀かも芚えおいたす。

ナヌザヌの数がチャットよりはるかに少ないため、チャット ゚ンゞンでランダム アクセス ディスク リク゚ストを保存するために、メッセヌゞをナヌザヌ ゚ンゞンにキャッシュしたす。

メッセヌゞ怜玢は、ナヌザヌ ゚ンゞンからこのナヌザヌのチャットを含むすべおのチャット ゚ンゞン むンスタンスぞの察角ク゚リずしお実装されたす。 結果はナヌザヌ ゚ンゞン自䜓で結合されたす。

すべおの詳现が考慮されたした。残っおいるのは、新しいスキヌムに切り替えるこずだけです。できればナヌザヌに気付かれずに。

デヌタ移行

したがっお、ナヌザヌごずにメッセヌゞを保存するテキスト ゚ンゞンず、マルチ チャット ルヌムずその䞭のナヌザヌに関するデヌタを保存する XNUMX ぀のクラスタヌ チャット メンバヌずメンバヌ チャットがありたす。 ここから新しいナヌザヌ ゚ンゞンずチャット ゚ンゞンに移行するにはどうすればよいでしょうか?

叀いスキヌムのメンバヌチャットは䞻に最適化のために䜿甚されおいたした。 必芁なデヌタをすぐにチャット メンバヌに転送したずころ、移行プロセスには参加しなくなりたした。

チャットメンバヌのキュヌ。 これには 100 のむンスタンスが含たれおいたすが、チャット ゚ンゞンには 4 のむンスタンスがありたす。 デヌタを転送するには、デヌタを準拠させる必芁がありたす。このために、チャット メンバヌは同じ 4 のコピヌに分割され、チャット ゚ンゞンでチャット メンバヌのバむナリログの読み取りが有効になりたした。
VKontakte メッセヌゞ デヌタベヌスを最初から曞き換えお生き残る
珟圚、チャット ゚ンゞンはチャット メンバヌからのマルチチャットに぀いおは認識しおいたすが、XNUMX 人の察話者ずの察話に぀いおはただ䜕も認識しおいたせん。 このようなダむアログは、ナヌザヌを参照しおテキスト ゚ンゞン内に配眮されたす。 ここでは、デヌタを「正面から」取埗したした。各チャット ゚ンゞン むンスタンスは、必芁なダむアログがあるかどうかをすべおのテキスト ゚ンゞン むンスタンスに尋ねたした。

玠晎らしい - チャット ゚ンゞンは、どのようなマルチチャット チャットがあるのか​​、どのような察話があるのか​​を認識しおいたす。
最終的に各チャットのメッセヌゞのリストが埗られるように、マルチチャット チャット内のメッセヌゞを結合する必芁がありたす。 たず、チャット ゚ンゞンは、このチャットからすべおのナヌザヌ メッセヌゞをテキスト ゚ンゞンから取埗したす。 堎合によっおは、非垞に倚くのメッセヌゞ (最倧数億) が存圚したすが、非垞にたれな䟋倖を陀いお、チャットは完党に RAM に収たりたす。 順序付けされおいないメッセヌゞがあり、それぞれが耇数のコピヌに分かれおいたす。結局のずころ、それらはすべお、ナヌザヌに察応するさたざたなテキスト ゚ンゞン むンスタンスから取埗されたものです。 目暙は、メッセヌゞを分類し、䞍必芁なスペヌスを占めるコピヌを削陀するこずです。

各メッセヌゞには、送信時刻ずテキストを含むタむムスタンプが付いおいたす。 ゜ヌトには時間を䜿甚したす。マルチチャット参加者の最も叀いメッセヌゞぞのポむンタヌを配眮し、目的のコピヌのテキストのハッシュを比范しお、タむムスタンプを増やす方向に進みたす。 コピヌのハッシュずタむムスタンプが同じになるのは論理的ですが、実際には必ずしもそうずは限りたせん。 芚えおいるずおり、叀いスキヌムでは同期は PHP によっお実行されおいたしたが、たれに、同じメッセヌゞの送信時間が異なるナヌザヌ間で異なるこずがありたした。 このような堎合、通垞は XNUMX 秒以内にタむムスタンプを線集できるようにしたした。 XNUMX 番目の問題は、受信者ごずにメッセヌゞの順序が異なるこずです。 このような堎合、ナヌザヌごずに異なる泚文オプションを備えた远加のコピヌを䜜成できるようにしたした。

この埌、マルチチャットのメッセヌゞに関するデヌタがナヌザヌ ゚ンゞンに送信されたす。 そしお、むンポヌトされたメッセヌゞには䞍快な特城がありたす。 通垞の動䜜では、゚ンゞンに送信されるメッセヌゞは、厳密に user_local_id の昇順で䞊べられたす。 叀い゚ンゞンからナヌザヌ ゚ンゞンにむンポヌトされたメッセヌゞは、この䟿利な特性を倱いたした。 同時に、テストの䟿宜のために、それらに玠早くアクセスし、その䞭で䜕かを探し、新しいものを远加できる必芁がありたす。

むンポヌトされたメッセヌゞを保存するために特別なデヌタ構造を䜿甚したす。

サむズのベクトルを衚したす VKontakte メッセヌゞ デヌタベヌスを最初から曞き換えお生き残るみんなはどこですか VKontakte メッセヌゞ デヌタベヌスを最初から曞き換えお生き残る - は異なり、芁玠の特別な順序で降順に䞊べられたす。 各セグメントにむンデックスが付いおいる VKontakte メッセヌゞ デヌタベヌスを最初から曞き換えお生き残る 芁玠が゜ヌトされたす。 このような構造内の芁玠の怜玢には時間がかかりたす VKontakte メッセヌゞ デヌタベヌスを最初から曞き換えお生き残る スルヌ VKontakte メッセヌゞ デヌタベヌスを最初から曞き換えお生き残る 二分探玢。 芁玠の远加は次の期間で償华されたす。 VKontakte メッセヌゞ デヌタベヌスを最初から曞き換えお生き残る.

そこで、叀い゚ンゞンから新しい゚ンゞンにデヌタを転送する方法を考え出したした。 しかし、このプロセスには数日かかりたす。そしお、その間にナヌザヌがお互いに手玙を曞く習慣をやめる可胜性は䜎いです。 この間にメッセヌゞが倱われないように、新旧䞡方のクラスタヌを䜿甚する䜜業スキヌムに切り替えたす。

デヌタはチャット メンバヌずナヌザヌ ゚ンゞンに曞き蟌たれたす (叀いスキヌムによる通垞の操䜜ずは異なり、テキスト ゚ンゞンには曞き蟌たれたせん)。 user-engine はリク゚ストを chat-engine にプロキシしたす。ここでの動䜜は、このチャットがすでにマヌゞされおいるかどうかによっお異なりたす。 チャットがただマヌゞされおいない堎合、チャット ゚ンゞンはメッセヌゞをそれ自䜓に曞き蟌たず、その凊理はテキスト ゚ンゞン内でのみ行われたす。 チャットがすでにチャット ゚ンゞンにマヌゞされおいる堎合は、chat_local_id がナヌザヌ ゚ンゞンに返され、メッセヌゞがすべおの受信者に送信されたす。 user-engine はすべおのデヌタを text-engine にプロキシしたす。そのため、䜕かが起こった堎合はい぀でもロヌルバックしお、珟圚のデヌタをすべお叀い゚ンゞンに保持できたす。 text-engine は user_local_id を返し、user_engine はこれを保存しおバック゚ンドに返したす。
VKontakte メッセヌゞ デヌタベヌスを最初から曞き換えお生き残る
その結果、移行プロセスは次のようになりたす。空のナヌザヌ ゚ンゞン クラスタヌずチャット ゚ンゞン クラスタヌを接続したす。 チャット ゚ンゞンはチャット メンバヌのバむナリログ党䜓を読み取り、䞊蚘のスキヌムに埓っおプロキシを開始したす。 叀いデヌタを転送し、XNUMX ぀の同期されたクラスタヌ (新旧) を取埗したす。 残っおいるのは、読み取りをテキスト ゚ンゞンからナヌザヌ ゚ンゞンに切り替え、プロキシを無効にするこずだけです。

結果

新しいアプロヌチのおかげで、゚ンゞンのすべおのパフォヌマンス指暙が改善され、デヌタの䞀貫性に関する問題が解決されたした。 メッセヌゞに新しい機胜をすぐに実装できるようになりたした (そしおすでに実装し始めおいたす - チャット参加者の最倧数を増やし、転送されたメッセヌゞの怜玢を実装し、固定メッセヌゞを開始し、ナヌザヌごずのメッセヌゞの合蚈数の制限を匕き䞊げたした) 。

ロゞックの倉曎は本圓に膚倧です。 そしお、これは必ずしも、倧芏暡なチヌムず無数のコヌド行による䜕幎もの開発を意味するわけではないこずに泚意したいず思いたす。 チャット ゚ンゞンずナヌザヌ ゚ンゞンに加えお、メッセヌゞ圧瞮のためのハフマン、スプレむ ツリヌ、むンポヌトされたメッセヌゞの構造などのすべおの远加ストヌリヌを含めたコヌドは 20 䞇行未満です。 そしお、これらは 3 人の開発者によっおわずか 10 か月で曞かれたした (ただし、次のこずに留意する必芁がありたす) すべお 3 デベロッパヌ - 䞖界チャンピオン スポヌツ番組で).

さらに、サヌバヌの数を 500 倍にする代わりに、その数を半分に枛らしたした。珟圚、ナヌザヌ ゚ンゞンずチャット ゚ンゞンは 5 台の物理マシン䞊で皌動しおいたすが、新しいスキヌムには負荷に察しお倧きな䜙裕がありたす。 蚭備にかかる費甚を倧幅に節玄できたした。幎間玄 750 䞇ドル + 運営費 XNUMX 䞇ドルを節玄できたした。

私たちは、最も耇雑で倧芏暡な問題に察しお最適な゜リュヌションを芋぀けるよう努めおいたす。 私たちにはたくさんの人材がいたす。だからこそ、デヌタベヌス郚門で有胜な開発者を探しおいたす。 このような問題が奜きで解決方法を知っおおり、アルゎリズムずデヌタ構造に関する優れた知識をお持ちの方は、ぜひチヌムに参加しおください。 お問い合わせください HR、 чтПбы узМать пПЎрПбМПстО.

この話があなたに関するものではない堎合でも、私たちは掚奚事項を重芖しおいるこずに泚意しおください。 友達に教えおください 開発者の欠員、そしお圌が詊甚期間を無事に完了するず、100䞇ルヌブルのボヌナスを受け取りたす。

出所 habr.com

コメントを远加したす