Prestoは、無料のオープンソースSQLクエリエンジンです。Metaでは、過去10年間にわたってこのエンジンを使っており、そこから多くのことを学んできました。ツール、プロセス、サービスなど、どんなものでも大規模に実行するとなると、予期しない課題を克服するために問題解決が必要になります。PrestoをMeta規模にまでスケールアップする過程で得られた4つの点、自分のクエリを大規模に実行しようとする際に役立つアドバイスについて以下に説明します。
図1: Prestoの新バージョン推進のプロセスワークフロー(フィリップ・S・ベルによる図)
Metaは、世界各地のデータセンターに及ぶ大量のPrestoクラスターを実行しています。Prestoは、大体少なくとも月1回、場合によっては月2回のペースで新バージョンがビルドされてデプロイ可能状態になっています。MetaにおけるPrestoのフットプリントが急速に拡大するにつれて直面した最も初期の課題は、クエリエンジンを大量のクラスターにデプロイしつつ、一貫性のある可用性と信頼性を確保するということでした。この点は、Prestoのインタラクティブな用途で、つまりユーザーがクエリを開始して結果をそのまま待っているという場合に特に当てはまっています。自動化された「バッチ」用途の場合は、クエリが失敗してもそれほど気になりません。というのも、自動再試行により結局は成功することになるからです。
その解決策はシンプルなものでした。Prestoクラスターはすべて、ゲートウェイと呼ばれるロードバランサーの背後に配置されています。ゲートウェイは、(Metaにある他のシステムとの連携により) Prestoクエリが適切なクラスターに送られるようにルーティングする作業を担当します。Prestoクラスターの更新が必要になると、まずゲートウェイから外されたものとしてマークされます。つまり、新たなクエリがルーティングされなくなります。自動化処理は、事前計算されたそのクラスター上で実行中のクエリが完了するのに必要な時間だけ待機します。その後、クラスターが更新され、オンラインになったなら、ゲートウェイから見えるようになり、クエリがそのクラスターへルーティングされるようになります。
Prestoの新リリースのデプロイに関する別の面は、可用性です。クラスター更新中もユーザーがPrestoを使えるようにする必要があります。ここでも、自動化処理により、あらゆる物理地域にあるあらゆるデータセンターに、常に必要な数のPrestoクラスターが確保されます。もちろん、一度にあまりにも多くのクラスターをダウンさせること(可用性の問題)と、一度にあまりにも少ないクラスターをダウンさせること(デプロイに長くかかりすぎる)との間の、適切なバランス点を見極めることが必要です。
図2: クラスターへのハードウェア追加の自動化ワークフロー(フィリップ・S・ベルによる図)
Metaにおけるデータウェアハウスは、複数地域にわたる分散がコンスタントに進んでいます。したがって、既存クラスターが定期的に撤去される間に、新しいPrestoクラスターを立ち上げる必要があります。かつてPrestoクラスターの数が少なかった時代に、これは手動で処理されていました。Metaのスケールアップが開始されると、変更すべてを手動でこなすことは、たちまち難しくなっていきました。この問題を解決するため、クラスターの立ち上げと撤去を処理する自動化処理を実装しました。
まずクラスター設定の標準化を図りました。つまり、MetaにおけるPrestoのさまざまな用途のための基本設定を構築しました。その上で、クラスターごとに基本設定に追加したりオーバーライドしたりする指定内容が最小限になるようにしました。このことが実現すると、ベースとなるテンプレートから設定を自動生成して、新しいクラスターを立ち上げることが可能になりました。また、クラスターの発展のためには、Tupperwareのようなさまざまな会社規模のインフラストラクチャサービスやデータウェアハウス固有サービスと統合するために、自動化フックと統合することが必要でした。クラスターがオンラインになると、少数のテストクエリがクラスターに送られ、自動化はクエリがクラスターによって問題なく実行されることを検証します。その後、そのクラスターがゲートウェイに登録され、クエリの処理を開始します。
クラスターの撤去は、まさにその逆の処理です。クラスターをゲートウェイから登録解除しますが、実行中のクエリがあればそれらが完了されるようにします。Prestoのプロセスがシャットダウンされ、クラスターの設定が削除されます。
この自動化が、データウェアハウスのハードウェアの立ち上げと撤去のワークフローに統合されています。最終的に、データセンターに出現した新しいハードウェアから、オンラインになってクエリを処理してハードウェア撤去時には切り離されるPrestoクラスターに至るまで、処理の全体が全面的に自動化されます。これを実装することにより、価値ある人工が節約され、ハードウェアアイドル時間が削減され、ヒューマンエラーが最小限になります。
図3: 不良ホスト検出(フィリップ・S・ベルによる図)
MetaにおけるPrestoの大規模デプロイが実現した今、オンコール(Prestoの問い合わせ対応担当者)の仕事を簡素化するようなツールや自動化が必要です。
Metaでは、オンコール担当者が効率的にデバッグしたり、発生する問題の根本原因を評価したりするのに役立つ複数の分析プログラムを、何年もかけて構築してきました。顧客レベルでのSLAの不備がある場合に、モニターシステムからアラートが出されます。そして分析プラグラムがトリガーされます。それらは、多種にわたるモニターシステム(オペレーショナルデータストア、ODS)、Scubaに公開されるイベント、さらにはホストレベルのログから情報を取得します。次に、分析プログラムのカスタムロジックにより、その情報がすべてまとめられて、可能性の高い根本原因が推測されます。これにより、オンコール担当者に根本原因の分析内容が提示され、可能と思われる対策オプションに直接移ることが可能になるため、非常に便利です。いくつかのケースについてはデバッグと修正処理の両方を完全自動化しており、その場合はオンコール担当者は全くノータッチで済みます。以下に若干の例を示します。
大量のマシン上で大規模にPrestoが実行されている場合、特定の「不良」ホストであまりにも多くのクエリが失敗することが明らかになりました。調査した結果、ホスト「不良」化のいくつかの根本原因を突き止めました。その中には、次のものが含まれます。
この問題に対処するため、Prestoクラスターでのクエリ失敗をモニタリングしています。具体的には、可能な場合にはクエリ失敗ごとに、その原因であるホストを識別します。また、特定のホストに起因するクエリ失敗が異常に多い場合に送出されるアラートを設定しています。その上で、自動化により、Prestoフリートから該当するホストを外して、失敗が発生しないようにします。
各Prestoクラスターでは、用途、ハードウェア設定、クエリのサイズに基づき、クエリの同時実行の最大値に達した時点で、そのクラスターに対するクエリをキューに入れる処理がサポートされています。Metaでは、Prestoクエリがそれを実行可能な「適切な」クラスターに送られるようにしつつ、リソースの利用を最適化するような洗練されたルーティングメカニズムが確立されています。ルーティングの判断には、Presto以外の複数のシステムも関係しており、複数の要素が考慮に入れられます。
このように複雑であるため、本番環境で検出されたキューの問題の根本原因をオンコール担当者が見極めるのは、非常に困難です。これも、複数の情報源から情報を入手して結論を示すことにより、分析プログラムが活躍する別のケースです。
図4: ロードバランサーの堅牢性(フィリップ・S・ベルによる図)
前述のように、Prestoクラスターは、MetaにおいてあらゆるPrestoクエリを1つずつルーティングするクエリロードバランサーの背後に位置しています。当初、Prestoの内部使用がまだ今日のようなレベルまでスケールアップしていなかった時代、ゲートウェイは非常にシンプルなものでした。しかし、Meta全体でPrestoの利用が高まってくると、何度かスケーラビリティの問題に直面することになりました。そのうちの1つは、高負荷によりゲートウェイで障害が発生するというものでした。それにより、すべてのユーザーがPrestoを利用できなくなることがありました。安定性に関する一部の問題の根本原因は、1つのサービスがゲートウェイに対して意図せずに短期間に何百万というクエリの集中砲火を浴びせるというものです。その結果、そのゲートウェイの処理がクラッシュし、クエリのルーティングが全くできなくなってしまっていました。
こういったシナリオを防ぐため、そのような意図しないDDoS的なトラフィックに対するゲートウェイの堅牢性と耐性を高めることに取り掛かりました。高負荷時にはクエリを拒否するスロットリング機能を実装しました。スロットリングは、グローバルレベルのすべてのクエリについて、ユーザー、ソース、IPごとなどさまざまなディメンションの1秒間のクエリ数に基づいて、アクティブにすることができます。実装した別の機能拡張は、自動スケーリングでした。ジョブのスケール調整をサポートするMeta規模のサービスを利用することにより、今ではゲートウェイのインスタンス数は動的なものとなっています。つまり、高負荷の場合にゲートウェイはスケールアップして、付加的なトラフィックを処理し、CPU/メモリを使い切らないで済むようになりました。このようにして、前述のクラッシュのシナリオを回避できます。したがって、スロットリング機能と併せて、ゲートウェイの堅牢性が確保され、予期できないトラフィックパターンの問題にも持ちこたえられるようになりました。
図5: Prestoアーキテクチャのスケーリング(フィリップ・S・ベルによる図)
Prestoをスケーリングアップする際に、覚えておくべき重要な点をいくつか以下に示します。
この記事は、Metaの生産技術者ニーラド・ソマンチ、およびMetaの開発者支援担当のフィリップ・ベルのコラボレーションにより執筆されました。
Prestoについてさらに詳しくは、prestodb.ioをご覧ください。また、フィリップ・ベルのPrestoの概要(YouTube)をご覧ください。あるいは、Twitter、Facebook、LinkedInでPrestoをフォローしてください。
Meta Open Sourceについて詳しくは、Metaのオープンソースサイトをご覧になるか、MetaのYouTubeチャンネルを登録するか、Twitter、Facebook、LinkedInでMetaをフォローしてください。