1712895832
2024-04-11 18:02:52
多くの企業と同様に、私たちもコア製品であるオープンソースの使用量ベースの課金プラットフォームである Lago を拡張する際に、途中でデータベース スタックを変更する必要がありました。 人気が高まるにつれて、毎分数百万のイベントを取り込むようになりました。 そして、私たちの初歩的な Postgres のみのスタックではうまくいきませんでした。 読み込み時間が長くなり、アプリ全体のパフォーマンスに影響を及ぼしていました。
いくつかの検討の結果、分散型 ClickHouse インスタンスをストリーミング イベント専用に使用することにしました。 当社の分析サービスは、OLAP データベースである ClickHouse に直接クエリできるようになりました。 他のすべてのデータのニーズについては、Postgres をそのまま使用しました。
戦略は成功しました。 リファクタリング以来、私たちは過去を振り返っていません。
今日は、ハイブリッド データベース スタックに関するその決定について、より具体的には、なぜ ClickHouse を使用することにしたのかについて説明します。
若手開発者を含むほとんどの開発者は、Postgres などの OLTP (オンライン トランザクション処理) データベースの使用経験があります。 名前が示すように、OLTP データベースは処理用に設計されています。 トランザクション。 トランザクションは、ソフトウェアがデータベースに対して呼び出すさまざまな種類の命令のうちの 1 つです。 最も一般的なものは、(i) 読み取り、(ii) 挿入、(iii) 更新、および (iv) 削除です。
OLTP データベースは通常、汎用データベースです。 あらゆるタイプのデータ処理をサポートしているため、あらゆるデータ問題に使用できます。 制限内で。 また、大規模であっても、以下を必要とするソフトウェアにとっては素晴らしいものです。
- アトミックトランザクション、グループ化された一連のトランザクションがすべて発生するか、まったく発生しないかのいずれかです。
- 一貫性、書き込みと更新の間のクエリは決定的で予測可能です。
ほとんどの問題にとって、これらは重要な性質です。 一部の人にとって、それらは重要です。 銀行アプリケーションでは、口座間で送金するときに不一致が発生することはできません。 こうした問題を解決するには、セントレベルの精度を実現する OLTP データベースが必要です。 現在でも Postgres を使用しています。 主要な データベース、構成済み [via our database.yml file](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/config/database.yml#L5)。 Ruby on Rail を使用していることを考えると、 [our Postgres schema](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/db/schema.rb) は Rail によって自動的に生成されます。 [Active Record](https://guides.rubyonrails.org/active_record_basics.html)、次のようなさまざまなモデルを管理する ORM [charges](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/spec/models/charge_spec.rb)、 [credit notes](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/spec/models/credit_note_spec.rb)、 [invoices](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/spec/models/invoice_spec.rb)、 [invites](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/spec/models/invite_spec.rb)、 [fees](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/spec/models/fee_spec.rb)、 [coupons](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/spec/models/coupon_spec.rb)、 そして [much, much more](https://github.com/getlago/lago-api/tree/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/spec/models)。 与えられたカスタムクエリをいくつか書きます [the performance limits of the ORM](https://github.com/getlago/lago/wiki/Is-ORM-still-an-%27anti-pattern%27%3F)、それ以外の場合は、ほとんどのトランザクションでアクティブ レコードに大きく依存します。
では、ClickHouse のような OLAP (オンライン分析処理) データベースはどこに登場するのでしょうか? Postgres は次のように設計されています。 厳密に 原子的で一貫性のある; データが完全に一致するために必要な 2 つのプロパティ 摂取した それらを処理するクエリが実行される前に。 これにより、エントリが 1 分あたり数百万単位で取り込まれるテーブル (たとえば、課金対象のイベント、特に管理対象サーバーなどのインフラストラクチャ サービスのイベント) では問題が発生します。 具体的には、問題 そうではありません データを取り込むだけでなく、キューをロックアップすることなく、高価な分析クエリを同時に処理します。 こうしたデータ要約の問題には、ClickHouse のような OLAP データベースが威力を発揮します。
OLAP データベースは、次の 2 つの主要な問題に対応して設計されています。(i) 複雑な読み取りクエリに効率的に応答する。 近似 精度、および (ii) 多数の書き込みクエリのバッチ処理。 ただし、OLAP データベースは ひどい データを変更する場合 (ここで、 全体 多くの場合、データベースを書き換えたり、データを削除したりする必要があります。
さまざまな OLAP ソリューション (ClickHouse、QuestDB、Druid など) にはそれぞれ異なる長所があります。次のセクションでは、ClickHouse を優れたソリューションにした具体的な特徴について詳しく説明します。 ただし、すべての OLAP ソリューションには共通の品質があります。つまり、データは Postgres などの OLTP データベースとは逆のレイアウトで保存されます。
ここで、ユーザーの観点から見ると、テーブルの列と行は単なる列と行のままです。 ただし、物理的にメモリ内では、データは行ごとではなく列ごとにスキャンされます。 これにより、関連するデータが順番に読み取られるため、特定のフィールドのすべての値を追加するなどの集計が非常に高速になります。
[ClickHouse](https://クリックハウス.com) は、Yandex の Web サイト分析製品で使用されるクローズドソース アルゴリズムからスピンアウトされたオープンソース ツールです。 現在、ClickHouse を守っているのは、 [ClickHouse Inc](https://clickhouse.com/company/our-story) による注目すべき貢献 [Altinity](https://altinity.com)。 現在まで、商業的にも質的にも最も成功した OLAP データベースの 1 つです。
ClickHouse には、分析の強力な手段となる 3 つの注目すべき機能があります。(i) 動的マテリアライズド ビュー、(ii) 専用エンジン、および (iii) ベクトル化されたクエリ実行です。
それぞれを要約すると、次のようになります。
- 動的 マテリアライズド ビュー。 マテリアライズド ビューは、基になるテーブルの生データから生成されるクエリ可能なビューです。 多くのデータベースが する Postgres を含むマテリアライズド ビューをサポートしているため、ClickHouse のマテリアライズド ビューは動的であり、新しいコンテンツが取り込まれるたびにコンテンツを効率的に更新します。 これらは、特定の時点のスナップショットにすぎず、更新に非常にコストがかかる通常のマテリアライズド ビューとは対照的です。
- 専用エンジン。 多くのデータベースには、ハードウェアを利用してクエリやトランザクションを処理する単一のエンジンがあります。 ただし、ClickHouse には、数値の合計や平均など、特定の数学関数用の専用エンジンがあります。
- ベクトル化されたクエリの実行。 ClickHouse の特殊なエンジンはベクトル化されたクエリ実行を利用しており、ハードウェアは複数のユニットを並行して使用して共通の結果を実現します (SIMD (単一命令、複数データ) として知られています)。
これらの特性を列型ストレージと組み合わせることで、ClickHouse はデータベース値を簡単に合計、平均、または一般的に集計することができます。
注意点として、Postgres はそうではありません。 全体的に 同様の結果を達成することはできませんが、最適化の砦を経由する必要があります。 たとえば、サードパーティがあります [vectorized executor](https://github.com/citusdata/postgres_vectorization_test) ClickHouse のネイティブ サポートを模倣する Postgres 用に設計されています。 もあります [a Fast Refresh Module](https://aws.amazon.com/blogs/database/building-fast-refresh-capability-in-amazon-rds-for-postgresql/) Postgres のログを使用してマテリアライズド ビューを動的に更新します。 Postgres トリガーと組み合わせることで、開発者は ClickHouse のようなセットアップを作成できます。 しかし、これらのテクニックにはすべて、 重要な セットアップ作業と追加のカラムにより、ClickHouse と同等の効率を達成できます。

関連する ミーム PostHog の Postgres と Clickhouse ガイドより
最近、Postgres と OLAP の分野で最も興味深い亀裂は次のとおりです。 [Hydra](https://www.ヒドラ.so)、オープンソースの列指向の Postgres ディストリビューションです。 とても 最近リリースされました (ClickHouse への移行後)。 私たちの意思決定期間中に Hydra が利用可能であったなら、私たちは別の選択をしていたかもしれません。 ただし、成熟した製品、大規模なコミュニティ、ハードウェアの最適化、Postgres との併用の使いやすさを考慮すると、ClickHouse は依然として信じられないほどの選択肢です。
もちろん、分析プロセスを ClickHouse に移行するだけでは、まだ半分にすぎません。 次は、実際に ClickHouse を運用環境にデプロイすることです。ここにはいくつかの戦略が存在します。
ClickHouse の実装について議論する場合、基本的に 2 つの異なるトピックがあります。ClickHouse の使用方法です。 のために、ClickHouse インスタンスがどのようにデプロイおよび維持されるかについて説明します。
ClickHouse インスタンス [ingests raw billable events](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/app/models/clickhouse/events_raw.rb#L3) ユーザーによって発送されます。 独自の ClickHouse スキーマは作成しませんが (ActiveRecord によって自動生成されるため)、ファイルに書き込まれます。 [available in our open-source repository](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/db/clickhouse_schema.rb#L4)。 ClickHouse インスタンスには 2 つのテーブルしかありません。raw_events そして raw_events_queue— 1 つの具体化されたビューと並行して、 events_raw_mv 。 それでおしまい。 その他の「ビジネスクリティカル」データは分析クエリではないため、ClickHouse には保存されません。
詳しくは、私たちの [raw_events_queue](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/db/clickhouse_migrate/20231026124912_create_events_raw_queue.rb) イベントが最初にストリーミングされる場所です。 [Apache Kafka](https://kafka.apache.org)、オープンソースのイベント ストリーミング ソフトウェア。 そこから、 [events_raw_mv](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/db/clickhouse_migrate/20231030163703_create_events_raw_mv.rb) ClickHouse で生成されます [cast()](https://clickhouse.com/docs/en/sql-reference/functions/type-conversion-functions) この関数は、イベントのメタデータを JSON BLOB から文字列配列にマップします。 最後に、この具体化されたビューはデータを [raw_events](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/db/clickhouse_migrate/20231024084411_create_events_raw.rb) テーブル。 これは [MergeTree](https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/mergetree) 大量の書き込みが発生しやすいテーブル。
raw_events Lago の一般的なコードベースは、 [ClickHouseStores](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/app/services/events/stores/clickhouse_store.rb#L14) クラス。次の場合にタップされます。 [aggregating billable metrics](https://github.com/getlago/lago-api/blob/e0da0a0b136577bffe5a1b8dac8747c913f7cdf1/app/services/billable_metrics/aggregation_factory.rb#L18)。 raw_events のタプルを使用します organization_id、 external_subscription_id、 code、および主キーとしてのタイムスタンプ。 ClickHouse の場合 [sophisticated support for primary key tuples](https://medium.com/datadenys/how-clickhouse-primary-key-works-and-how-to-choose-it-4aaf3bf4a8b9)、これは ClickHouse が行を見つけるのに役立ちます とても 素早く。
ClickHouse はオープンソース データベースであるため、通常の Linux サーバー上で自己ホストすることができます。 ただし、多くの企業はマネージド データベース ソリューションを信頼しています。その理由は、(i) 全体的なコストが削減されることが多く、(ii) データベースの拡張が容易になり、(iii) 安全なレプリケーション/バックアップが行われるからです。
最も人気のあるオプションの 1 つは、ClickHouse Inc の ClickHouse Cloud 製品です。これは、コンピューティングとストレージが分離されたサーバーレス ClickHouse インスタンスを提供します。
ただし、代わりに、既存のクラウド製品の Kubernetes クラスターに ClickHouse をデプロイおよび管理する Altinity Operator を選択しました。 カスタム定義による柔軟性、コスト効率、メンテナンスの容易さなどを考慮すると、このアプローチを好みました。
ClickHouse を使用するオープンソース プロジェクトは私たちだけではありません。 実際、Postgres から ClickHouse に移行したオープンソース プロジェクトは私たちだけではありません。 注目すべき例は、 [PostHog](https://posthog.com)、から切り替えられたオープンソースの分析スイート [Postgres to ClickHouse](https://posthog.com/blog/clickhouse-payment) 1 秒あたりに処理していた Web イベントの量が膨大であることを考えると。
もう 1 つの優れた例は、ClickHouse を使用してストリーミング イベントのデータを保存した Gitlab です。 [in their observability suite](https://docs.gitlab.com/ee/architecture/blueprints/clickhouse_usage/)。 一般に、オープンソース企業 (およびクローズドソース プロジェクトも同様) が規模を拡大し始めると、Postgres や mySQL などの汎用データベースが不向きであることがわかります。
HTTP データ ストリーミング製品 TinyBird などの一部のクローズド ソース ソリューションでも、 [open-source contributions to ClickHouse](https://www.tinybird.co/blog-posts/we-launched-an-open-source-clickhouse-knowledge-base)それに依存していることを考えると。 ゆっくりとですが、ClickHouse は、Postgres が OLTP 分野で達成しているのと同じレベルの成功を OLAP の世界で築き上げています。
テーブル レイアウトを反転するハードウェアの最適化により、アプリケーションの規模に合わせて万能のデータベースは存在しません。 当社の製品はイベントが多い性質を持っていたため、この問題は取り組みのかなり早い段階で発生しました。 ただし、すべてのチームが OLTP + OLAP スタックから始める必要があるというわけではありません。単に、その瞬間が来たときに備えられるようにするためです。
#Clickhouse #を使用してイベント #エンジンをスケールする #getlagolago #Wiki #GitHub