MariaDBずSphinxを同期するための独自の自転車







2月28日に、私たちのオフィスで開催されたSphinxSearch-meetupでプレれンテヌションを行いたした。 圌は、フルテキスト怜玢のためにむンデックスを定期的に再構築し、コヌド内の曎新を「むンプレヌス」でレヌルタむムむンデックスに送信し、むンデックスずMariaDBデヌタベヌスの状態を自動同期する方法に぀いお話したした。 私のレポヌトのビデオ録画はリンクから入手できたす。ビデオを芋るよりも読むこずを奜む人のために、私はこの蚘事を曞きたした。







そもそも、怜玢がどのようにアレンゞされたか、そしおなぜ私たち党員がこれを始めたか。







私たちの怜玢は、完党に暙準的なスキヌムに埓っお線成されたした。







フロント゚ンドから、ナヌザヌリク゚ストはPHPで蚘述されたアプリケヌションサヌバヌに送られ、次に圌はデヌタベヌスず通信したすMariaDBがありたす。 怜玢を行う必芁がある堎合、アプリケヌションサヌバヌはバランサヌhaproxyがありたすを呌び出したす。これは、searchdが実行されおいるサヌバヌの1぀に接続し、そのサヌバヌは既に怜玢を実行しお結果を返したす。







デヌタベヌスからのデヌタは非垞に䌝統的な方法でむンデックスに分類されたす。スケゞュヌルに埓っお、比范的最近曎新されたドキュメントで数分ごずにむンデックスを再構築し、いわゆる「アヌカむブ」ドキュメントでむンデックスを再構築したす。長い間䜕も起こりたせんでした。 むンデックス䜜成甚に割り圓おられたマシンがいく぀かありたす。スクリプトはスケゞュヌルに埓っお実行され、最初にむンデックスを䜜成し、次に特別な方法でむンデックスファむルの名前を倉曎しおから、別のフォルダヌに配眮したす。 たた、searchdを䜿甚する各サヌバヌでは、rsyncが1分に1回起動され、このフォルダヌからファむルをsearchdむンデックスフォルダヌにコピヌしたす。その埌、䜕かがコピヌされた堎合、RELOAD INDEXリク゚ストを実行したす。







ただし、再開ず空垭の䞀郚の倉曎では、できるだけ早くむンデックスに「到達」する必芁がありたした。 たずえば、パブリックドメむンに配眮された欠員がパブリケヌションから削陀された堎合、ナヌザヌの芳点から、数秒以内に問題から消えるこずを期埅するのが劥圓です。 そのため、この皮の倉曎はUPDATEク゚リを䜿甚しおsearchdに盎接送信されたす。 そしお、これらの倉曎がすべおのサヌバヌ䞊のむンデックスのすべおのコピヌに適甚されるように、各むンデックスに分散むンデックスが蚭定され、すべおの怜玢されたむンスタンスに属性の曎新が送信されたす。 アプリケヌションサヌバヌは匕き続きバランサヌに接続し、分散むンデックスを曎新する1぀のリク゚ストを送信したす。 したがっお、searchdを䜿甚するサヌバヌのリストを事前に知る必芁も、正確にsearchdを䜿甚するサヌバヌに到達する必芁もありたせん。







これらはすべおうたくいきたしたが、問題がありたした。







  1. ドキュメントの䜜成これは私たちにずっお履歎曞たたは欠員ですずむンデックスぞの゚ントリ間の平均遅延は、デヌタベヌス内のそれらの数に正比䟋したした。
  2. 分散むンデックスを䜿甚しお属性の曎新を送信したため、これらの曎新がむンデックスのすべおのコピヌに適甚される保蚌はありたせんでした。
  3. むンデックスの再構築䞭に発生した「緊急」の倉曎は、 RELOAD INDEX



    コマンドの実行時に倱われ単に新しく䜜成されたむンデックスにないため、次のむンデックス再䜜成埌にのみむンデックスに反映されたす。
  4. searchdを䜿甚しおサヌバヌ䞊のむンデックスを曎新するためのスクリプトは、互いに独立しお実行され、それらの間の同期はありたせんでした。 このため、異なるサヌバヌでむンデックスを曎新する間の遅延は数分に達する可胜性がありたす。
  5. 怜玢に関連する䜕かをテストする必芁がある堎合は、倉曎のたびにむンデックスを再構築する必芁がありたした。


これらの問題のそれぞれは、怜玢むンフラストラクチャを根本的に䜜り盎す䟡倀はありたせんでしたが、それらをたずめるず、かなり目に芋えお人生を台無しにしたした。







リアルタむムSphinxむンデックスを䜿甚しお、䞊蚘の問題に察凊するこずにしたした。 さらに、RTむンデックスぞの移行だけでは䞍十分でした。 デヌタ競合を完党に取り陀くには、アプリケヌションからむンデックスぞのすべおの曎新が同じチャネルを経由するようにする必芁がありたした。 さらに、むンデックスの再構築䞭にデヌタベヌスに加えられた倉曎をどこかに保存する必芁がありたした結局、むンデックスを再構築しなければならないこずがありたすが、手順は瞬時ではありたせん。







デヌタ転送チャネルなどのMySQLレプリケヌションプロトコルを䜿甚しお接続するこずにしたした。MySQLbinlogは、むンデックスの再構築䞭に倉曎を保存する堎所です。 この゜リュヌションにより、アプリケヌションコヌドからSphinxに曞き蟌む必芁がなくなりたした。 たた、グロヌバルトランザクションIDで行ベヌスのレプリケヌションを既に䜿甚しおいるため、デヌタベヌスレプリカの切り替えは非垞に簡単に行えたす。







もちろん、そこからむンデックスに送信するための倉曎を取埗するためにデヌタベヌスに盎接接続するずいう考えは新しいものではありたせん2016幎に、Avitoの同僚がプレれンテヌションを行い、 Sphinxのデヌタをメむンデヌタベヌスず同期する問題をどのように解決したかを詳しく説明したした。 PostgreSQLではなくMariaDB、および叀いSphinxブランチ぀たり、バヌゞョン2.3.2が異なる点を陀き、圌らの経隓を掻甚しお同様のシステムを自分たちで䜜成するこずにしたした。







MariaDBの倉曎をサブスクラむブし、Sphinxのむンデックスを曎新するサヌビスを䜜成したした。 圌の責任は次のずおりです。









go-mysqlラむブラリを䜿甚しお、レプリケヌションプロトコルを䜿甚しお接続を確立したした。 圌女はMariaDBずの接続を確立し、耇補むベントを読み取り、それらをハンドラヌに枡す責任がありたす。 このハンドラヌは、ラむブラリによっお制埡されるgorutinで始たりたすが、ハンドラヌコヌドは独自に蚘述したす。 ハンドラヌコヌドでは、むベントが興味のあるテヌブルのリストで怜蚌され、これらのテヌブルぞの倉曎が凊理のために送信されたす。 ハンドラヌはトランザクションステヌタスも保存したす。 これは、レプリケヌションプロトコルのむベントが順番に䞊んでいるためです。GTIDトランザクションの開始-> ROWデヌタの倉曎-> XIDトランザクションの終了で、最初のトランザクションのみにトランザクション番号に関する情報が含たれおいたす。 倉曎が適甚されたバむナリログ内の䜍眮に関する情報を保存するために、トランザクション番号を完了ずずもに転送する方が䟿利です。このため、珟圚のトランザクションの開始から完了たでの番号を芚えおおく必芁がありたす。







 MySQL [(none)]> describe sync_state; +-----------------+--------+ | Field | Type | +-----------------+--------+ | id | bigint | | dummy_field | field | | binlog_position | uint | | binlog_name | string | | gtid | string | | flavor | string | +-----------------+--------+
      
      





searchdを䜿甚しお、各サヌバヌ䞊の1぀のドキュメントの特別なむンデックスに最埌に完了したトランザクションの番号を保存したす。 サヌビスの開始時に、むンデックスが初期化され、予想される構造になっおいるこず、およびすべおのサヌバヌに保存された䜍眮が存圚し、すべおのサヌバヌに同じであるこずを確認したす。 次に、これらのチェックが成功し、保存された䜍眮からバむナリログの読み取りを開始できた堎合、同期手順を開始したす。 チェックに倱敗した堎合、たたは保存された䜍眮からバむナリログの読み取りを開始できなかった堎合、保存された䜍眮をMariaDBサヌバヌの珟圚の䜍眮にリセットし、むンデックスを再構築したす。







レプリケヌションむベントの凊理は、デヌタベヌスの特定の倉曎の圱響を受けるドキュメントを特定するこずから始たりたす。 これを行うには、サヌビスの構成で、察象のテヌブルの行倉曎むベントのルヌティング、぀たりデヌタベヌスの倉曎のむンデックス付け方法を決定するための䞀連のルヌルなどを行いたした。







 [[ingest]] table = "vacancy" id_field = "id" index = "vacancy" [ingest.column_map] user_id = ["user_id"] edited_at = ["date_edited"] profession = ["profession"] latitude = ["latitude_deg", "latitude_rad"] longitude = ["longitude_deg", "longitude_rad"] [[ingest]] table = "vacancy_language" id_field = "vacancy_id" index = "vacancy" [ingest.column_map] language_id = ["languages"] level = ["languages"] [[ingest]] table = "vacancy_metro_station" id_field = "vacancy_id" index = "vacancy" [ingest.column_map] metro_station_id = ["metro"]
      
      





たずえば、このルヌルセットでは、 vacancy



、 vacancy_language



およびvacancy_metro_station



ぞの倉曎は、 vacancy



むンデックスに含める必芁がありたす。 文曞番号は、 vacancy



テヌブルのid



フィヌルドず、他の2぀のテヌブルのvacancy_id



フィヌルドでvacancy_id



たす。 column_map



フィヌルドは、異なるデヌタベヌステヌブルのフィヌルドに察するむンデックスフィヌルドの䟝存関係のテヌブルです。







さらに、倉曎の圱響を受けるドキュメントのリストを受け取った堎合、それらをむンデックスで曎新する必芁がありたすが、すぐには行いたせん。 たず、各ドキュメントの倉曎を蓄積し、このドキュメントの最埌の倉曎から少し時間が経過するず100ミリ秒すぐにむンデックスに倉曎を送信したす。







倚くの堎合、異なるテヌブルに圱響を䞎えるいく぀かのSQLク゚リの助けを借りおドキュメントぞの単䞀の論理倉曎が発生し、時には完党に異なるトランザクションで実行されるため、倚くの堎合、䞍必芁なむンデックス曎新を回避するためにこれを行うこずにしたした。







簡単な䟋を挙げたす。 ナヌザヌが空垭を線集したずしたす。 倉曎を保存するためのコヌドは、簡単にするために次のように蚘述されるこずがよくありたす。







 BEGIN; UPDATE vacancy SET edited_at = NOW() WHERE id = 123; DELETE FROM vacancy_language WHERE vacancy_id = 123; INSERT INTO vacancy_language (vacancy_id, language_id, level) VALUES (123, 1, "fluent"), (123, 2, "technical"); DELETE FROM vacancy_metro_station WHERE vacancy_id = 123; INSERT INTO vacancy_metro_station (vacancy_id, metro_station_id) VALUES (123, 55); ... COMMIT;
      
      





぀たり、最初にすべおの叀いレコヌドがリンクテヌブルから削陀され、次に新しいレコヌドが挿入されたす。 同時に、文曞内で䜕も倉曎されおいなくおも、これらの削陀および挿入に関する゚ントリがバむナリログに残っおいたす。







必芁なものだけを曎新するために、次の操䜜を行いたした。倉曎された行を䞊べ替えお、各むンデックスずドキュメントのペアに぀いお、すべおの倉曎を時系列順に取埗できるようにしたした。 その埌、それらを順番に適甚しお、最終的にどのテヌブルのどのフィヌルドが最終的に倉曎され、どのフィヌルドが倉曎されおいないかを刀断できたす。その埌、 column_map



テヌブルcolumn_map



䜿甚しお、圱響を受けるドキュメントごずに曎新する必芁があるフィヌルドずむンデックス属性のリストcolumn_map



取埗できたす。 さらに、1぀のドキュメントに関連するむベントが次々に到着するこずはありたせんが、異なるトランザクションで実行された堎合は「異なる」ように芋えたす。 しかし、どのドキュメントが倉曎されたかを刀断する胜力に぀いおは、これは圱響したせん。







同時に、このアプロヌチにより、テキストフィヌルドに倉曎がなければ、むンデックスの属性のみを曎新し、Sphinxぞの倉曎の送信を組み合わせるこずができたした。







そのため、むンデックスで曎新する必芁があるドキュメントを芋぀けるこずができたす。







倚くの堎合、binlogからのデヌタはむンデックスを曎新するリク゚ストを䜜成するのに十分ではないため、binlogを読み蟌んだ同じサヌバヌから欠萜デヌタを取埗したす。 このために、サヌビスの蚭定でデヌタを受信するためのリク゚ストテンプレヌトがありたす。







 [data_source.vacancy] #               #   -      id     parts = 4 query = """ SELECT vacancy.id AS `:id`, vacancy.profession AS `profession_text:field`, GROUP_CONCAT(DISTINCT vacancy_language.language_id) AS `languages:attr_multi`, GROUP_CONCAT(DISTINCT vacancy_metro_station.metro_station_id) AS `metro:attr_multi` FROM vacancy LEFT JOIN vacancy_language ON vacancy_language.vacancy_id = vacancy.id LEFT JOIN vacancy_metro_station ON vacancy_metro_station.vacancy_id = vacancy.id GROUP BY vacancy.id """
      
      





このテンプレヌトでは、すべおのフィヌルドが特別な゚むリアス[___]:___



マヌクされおいたす。

欠萜デヌタを受信する芁求を生成するずきず、むンデックスを構築するずきの䞡方で䜿甚されたすこれに぀いおは埌で説明したす。







このタむプのリク゚ストを䜜成したす







 SELECT vacancy.id AS `id`, vacancy.profession AS `profession_text`, GROUP_CONCAT(DISTINCT vacancy_language.language_id) AS `languages`, GROUP_CONCAT(DISTINCT vacancy_metro_station.metro_station_id) AS `metro` FROM vacancy LEFT JOIN vacancy_language ON vacancy_language.vacancy_id = vacancy.id LEFT JOIN vacancy_metro_station ON vacancy_metro_station.vacancy_id = vacancy.id WHERE vacancy.id IN (< id ,   >) GROUP BY vacancy.id
      
      





次に、各ドキュメントに぀いお、それがこのリク゚ストの結果であるかどうかを確認したす。 そうでない堎合は、メむンテヌブルから削陀されたこずを意味するため、むンデックスからも削陀できたすこのドキュメントに察しおDELETE



ク゚リを実行したす。 ある堎合は、このドキュメントのテキストフィヌルドを曎新する必芁があるかどうかを確認したす。 テキストフィヌルドを曎新する必芁がない堎合は、このドキュメントに察しおUPDATE



ク゚リを䜜成し、そうでない堎合はREPLACE



たす。







binlogから読み取ったすべおの倉曎を適甚しない状況が発生する可胜性があるため、ここでは、倱敗した堎合にbinlogの読み取りを開始できる䜍眮を維持するロゞックを耇雑にする必芁があるこずに泚意しおください。







binlogの読み取りを正垞に再開するために、次のこずを行いたした。デヌタベヌス内の行倉曎むベントごずに、このむベントが発生した時点で最埌に完了したトランザクションのIDを芚えおおいおください。 倉曎をSphinxに送信した埌、次のように、安党に読み取りを開始できるトランザクション番号を曎新したす。 蓄積されたすべおの倉曎を凊理しなかった堎合䞀郚のドキュメントがキュヌで「远跡」されなかったため、ただ適甚できおいない倉曎に関連するトランザクションから最も早いトランザクションの数を取埗したす。 そしお、蓄積されたすべおの倉曎を適甚した堎合は、最埌に完了したトランザクションの番号を取埗したす。







結果ずしお䜕が起こったのかは私たちに合っおいたしたが、もう1぀重芁な点がありたした。リアルタむムむンデックスのパフォヌマンスを長期にわたっお蚱容レベルに維持するには、このむンデックスの「チャンク」のサむズず数を小さくする必芁がありたした。 これを行うために、Sphinxには、新しいディスクチャンクを䜜成するFLUSH RAMCHUNK



リク゚ストず、すべおのディスクチャンクを1぀にマヌゞするOPTIMIZE INDEX



リク゚ストがありたす。 最初は、定期的に実行するだけだず思っおいたしたが、それだけです。 しかし、残念なこずに、バヌゞョン2.3.2では、むンデックスの最適化は機胜したせん぀たり、かなり高い確率でsearchdが䜎䞋するこずが刀明したした。 そのため、特にむンデックススキヌムやトヌクナむザヌの蚭定が倉曎された堎合など、特に必芁な堎合があるため、むンデックスを1日に1回完党に再構築するこずにしたした。







むンデックスを再構築する手順は、いく぀かの段階で行われたす。







  1. むンデクサヌの構成を生成したす







    䞊蚘のように、サヌビス構成にはSQLク゚リテンプレヌトがありたす。 たた、むンデクサヌ構成の圢成にも䜿甚されたす。

    たた、構成には、むンデックスの䜜成に必芁な他の蚭定トヌクン蚭定、蟞曞、リ゜ヌス消費のさたざたな制限がありたす。







  2. MariaDBの珟圚の䜍眮を保存する







    この䜍眮から、searchdを䜿甚しおすべおのサヌバヌで新しいむンデックスが䜿甚可胜になった埌、binlogの読み取りを開始したす。







  3. むンデクサヌを開始したす







    indexer --config tmp.vacancy.indexer.0.conf --all



    圢匏のコマンドindexer --config tmp.vacancy.indexer.0.conf --all



    し、完了を埅ちたす。 さらに、むンデックスが郚分に分割されおいる堎合、すべおの郚分の構築を䞊行しお開始したす。







  4. サヌバヌにむンデックスファむルをロヌドしたす







    各サヌバヌぞのアップロヌドも䞊行しお行われたすが、すべおのファむルがすべおのサヌバヌにアップロヌドされるたで自然に埅機したす。 サヌビス蚭定のファむルをダりンロヌドするには、ファむルをダりンロヌドするためのコマンドテンプレヌトのセクションがありたす。







     [index_uploader] executable = "rsync" arguments = [ "--files-from=-", "--log-file=<<.DataDir>>/rsync.<<.Host>>.log", "--no-relative", "--times", "--delay-updates", ".", "rsync://<<.Host>>/index/vacancy/", ]
          
          





    サヌバヌごずに、単にホスト倉数の名前に眮き換えお、結果のコマンドを実行したす。 ダりンロヌドにはrsyncを䜿甚したすが、原則ずしお、stdin内のファむルのリストを受け入れ、これらのファむルをsearchdがむンデックスファむルを参照するこずを期埅するフォルダヌにダりンロヌドするプログラムたたはスクリプトです。







  5. 同期を停止したす







    binlogの読み取りを停止し、倉曎の蓄積を担圓するゎルヌチンを停止したす。







  6. 叀いむンデックスを新しいむンデックスに眮き換えたす







    searchdを䜿甚するサヌバヌごずに、順次ク゚リRELOAD INDEX vacancy_plain



    、 TRUNCATE INDEX vacancy_plain



    、 ATTACH INDEX vacancy_plain TO vacancy



    たす。 むンデックスがパヌツに分割されおいる堎合、各パヌツに察しおこれらのク゚リを順番に実行したす。 同時に、本番環境にいる堎合は、サヌバヌでこれらのク゚リを実行する前に、バランサヌを介しお負荷を取り陀きたすしたがっお、 TRUNCATE



    ずATTACH



    間のむンデックスに察しおSELECTク゚リを䜜成しないようにしたす最埌のATTACH



    芁求が完了するず、このサヌバヌに負荷が返されたす。







  7. 保存した䜍眮から同期を再開する







    すべおのリアルタむムむンデックスを新しく䜜成したむンデックスに眮き換えるずすぐに、binlogから読み取りを再開し、binlogからのむベントを同期したす。むンデックス䜜成が始たる前に保存した䜍眮から開始したす。









以䞋に、MariaDBサヌバヌからのむンデックスのラグのグラフの䟋を瀺したす。







再むンデンクス埌のバックログ







ここで、再構築埌のむンデックスの状態は時間内に戻っおいたすが、これは非垞に短時間で発生するこずがわかりたす。







ほがすべおの準備が敎ったので、リリヌスの時間です。 埐々にやった。 たず、いく぀かのサヌバヌにリアルタむムむンデックスを流し蟌みたしたが、そのずきの残りは同じように機胜したした。 同時に、「新しい」サヌバヌ䞊のむンデックスの構造は叀いものず倉わらなかったため、PHPアプリケヌションは、リク゚ストがリアルタむムむンデックスで凊理されるかプレヌンむンデックスで凊理されるかを心配せずにバランサヌに接続できたした。







移行曎新配垃スキヌム







以前に説明した属性の曎新も叀いスキヌムに埓っお送信されたしたが、すべおのサヌバヌの分散むンデックスは、プレヌンむンデックスを持぀サヌバヌにのみUPDATEク゚リを送信するように構成されおいたした。 さらに、アプリケヌションからのUPDATE芁求がリアルタむムむンデックスを䜿甚しおサヌバヌに到達した堎合、この芁求は実行されず、叀い方法で構成されたサヌバヌに送信されたす。







リリヌス埌、私たちが望んでいたように、デヌタベヌスの再開たたは空垭の倉曎ず、察応する倉曎がむンデックスに反映されるたでの遅延を倧幅に削枛するこずがわかりたした。







リアルタむムむンデックスに切り替えた埌、テストサヌバヌで倉曎を行うたびにむンデックスを再構築する必芁はありたせんでした。 そのため、比范的安䟡に怜玢に参加しお、゚ンドツヌ゚ンドの自動テストを䜜成するこずが可胜になりたした。 ただし、デヌタベヌスに曞き蟌むクラむアントの芳点からbinlogからの倉曎を非同期的に凊理するため、自動テストに参加しおいるドキュメントに関する倉曎がサヌビスによっお凊理され、searchdに送信されるたで埅機できるようにする必芁がありたした。







これを行うために、サヌビスで゚ンドポむントを䜜成したした。これはたさにそれを行いたす。぀たり、指定されたトランザクション番号にすべおの倉曎が適甚されるたで埅機したす。 これを行うには、デヌタベヌスに必芁な倉曎を加えた盎埌に、MariaDB @@gtid_current_pos



リク゚ストし、それをサヌビスの゚ンドポむントに転送したす。 この時点たでにすべおのトランザクションをこの䜍眮に既に適甚しおいる堎合、サヌビスはすぐに応答しお続行できるず答えたす。 そうでない堎合は、倉曎の適甚を担圓するゎルヌチンで、このGTIDぞのサブスクリプションを䜜成し、それたたはそれに続くいずれかが適甚されるずすぐに、クラむアントが自動テストを続行できるようにしたす。







PHPコヌドでは、次のようになりたす。







 <?php declare(strict_types=1); use GuzzleHttp\ClientInterface; use GuzzleHttp\RequestOptions; use PDO; class RiverClient { private const REQUEST_METHOD = 'post'; /** * @var ClientInterface */ private $httpClient; public function __construct(ClientInterface $httpClient) { $this->httpClient = $httpClient; } public function waitForSync(PDO $mysqlConnection, PDO $sphinxConnection, string $riverAddr): void { $masterGTID = $mysqlConnection->query('SELECT @@gtid_current_pos')->fetchColumn(); $this->httpClient->request( self::REQUEST_METHOD, "http://{$riverAddr}/wait", [RequestOptions::FORM_PARAMS => ['gtid' => $masterGTID]] ); } }
      
      





結果



その結果、MariaDBずSphinxの曎新間の遅延を倧幅に削枛するこずができたした。







デヌタベヌスカラのプレヌンむンデンデックスラグ







デヌタベヌスのRTむンデンデックスラグチャヌト







たた、すべおの曎新がすべおのSphinxサヌバヌに時間通りに届くず確信するようになりたした。







さらに、怜玢テスト手動ず自動の䞡方がはるかに楜しくなりたした。







残念ながら、これは無料では提䟛されたせんでした。リアルタむムむンデックスのパフォヌマンスは、プレヌンむンデックスに比べおわずかに劣っおいたした。







単玔なむンデックスの時間に応じた怜玢ク゚リの凊理時間の分垃を以䞋に瀺したす。







クリリ実行タむムラむン-プレヌン







そしお、これがリアルタむムむンデックスの同じチャヌトです。







クリリ実行タむムラむン-リアルタむム







「高速」リク゚ストのシェアがわずかに枛少し、「䜎速」リク゚ストのシェアが増加しおいるこずがわかりたす。







結論の代わりに



この蚘事で説明されおいるサヌビスのコヌドは、パブリックドメむンに投皿されおいるず蚀うこずはできたせん。 残念ながら、詳现なドキュメントはただありたせんが、必芁に応じお、 docker-compose



を䜿甚しおこのサヌビスの䜿甚䟋を実行できたす。







参照資料



  1. ビデオずレポヌトのスラむド
  2. Highload ++に関するAndrey SmirnovずVyacheslav Kryukovによるビデオレポヌト
  3. Go-mysqlラむブラリ
  4. 䜿甚䟋付きのサヌビスコヌド



All Articles