導入
ClickHouseは、高性能なOLAPクエリとリアルタイム分析に優れたオープンソースの列指向データベース管理システムです。しかし、ClickHouseのデータストレージの拡張は、特にデータ量が増加するにつれて困難になる場合があります。効率的な解決策の一つは、階層型ストレージを使用することです。階層型ストレージを使用すると、アクセス頻度の低いデータはよりコスト効率の高いストレージに移動し、頻繁にアクセスするデータはより高速で高価なストレージに保持できます。ClickHouseは、ローカルディスクやDigitalOcean Spacesなどのリモートオプションなど、さまざまなデータストレージバックエンドをサポートしています。大量のデータを管理する場合、複数のストレージデバイスを使用するのが一般的です。.
DigitalOcean Spacesは、ClickHouseの階層型ストレージアーキテクチャにレイヤーとして統合できるオブジェクトストレージサービスです。このガイドでは、ClickHouseクラスターの階層型ストレージオプションとしてDigitalOcean Spacesを設定する手順を詳しく説明します。.
このガイドでは、ClickHouseにバッチログを送信するシンプルなGoアプリケーションを構築します。まず、ログはホットストレージ(デフォルトのディスク、ローカルとも呼ばれます)に保存され、指定された時間間隔(2分)が経過するとコールドストレージ(例えば、DO SpacesのようなS3ベースのストレージ)に移動されます。.
前提条件
始める前に、次のものがあることを確認してください。
- DigitalOcean のクラウド アカウント。.
- DigitalOcean Spaces バケット。.
- DigitalOcean Spaces へのアクセス キー。.
- ClickHouse 構成とオブジェクト ストレージの基本的な紹介。.
ステップ1 - DigitalOcean Spaceを作成して設定する
DigitalOcean Cloudアカウントにログインし、新しいスペース(バケット)を作成します。このバケットは、アクセス頻度の低いデータ用の階層型ストレージとして使用されます。.
- ダッシュボードのスペースセクションに移動します。.
- 「新しいスペースを作成」をクリックし、名前を入力し、地域を選択して、権限を設定します。.
- エンドポイント URL をメモします。.
- 次の手順で必要になるので、アクセス キーとシークレット キーをメモしておいてください。.
この時点で、バケットが作成され、ClickHouse と統合する準備が整います。.
ステップ2 - DockerコンテナでClickHouseサーバーをセットアップする
まず、フォルダーを作成し、「clickhouse」という名前を付けます。.
mkdir clickhouseこのフォルダに Dockerfile を作成し、値 {YOUR_AWS_ACCESS_KEY_ID} と {YOUR_AWS_SECRET_ACCESS_KEY} をアクセスキーとシークレットキーに置き換えます。.
FROM clickhouse/clickhouse-server:latest
# Copy the config file to the container
COPY storage.xml /etc/clickhouse-server/config.d/storage.xml
# Copy the S3 table creation script
COPY create.sql /docker-entrypoint-initdb.d/
# Set environment variables for S3 credentials
ENV AWS_ACCESS_KEY_ID={YOUR_AWS_ACCESS_KEY_ID}
ENV AWS_SECRET_ACCESS_KEY={YOUR_AWS_SECRET_ACCESS_KEY}
# Expose ClickHouse HTTP and native ports
EXPOSE 8123 9000
USER clickhouse
# --config-file ./programs/server/config.xml
CMD ["clickhouse-server", "--config-file", "/etc/clickhouse-server/config.xml"]説明:
- access_key_id と secret_access_key: これらは DigitalOcean Spaces の資格情報です。.
警告: このガイドでは、簡潔にするために Dockerfile に資格情報を含めていますが、この方法は実稼働環境では推奨されません。.
ステップ3 - S3互換ストレージ用にClickHouseを構成する
このステップでは、ClickHouse が DigitalOcean Spaces をストレージシステムの階層として使用できるように設定を行います。これには、ClickHouse インストールの config.xml ファイルにストレージ設定を追加することが含まれます。.
Spacesバケットをストレージディスクとして使用するには、まずClickHouse設定ファイルで宣言する必要があります。既存のconfig.xmlファイルを変更するか、conf.dフォルダに新しいファイルを追加して、後でconfig.xmlにマージすることをお勧めします。.
<clickhouse>
<storage_configuration>
<disks>
<s3>
<type>s3</type>
<endpoint>{YOUR_S3_SPACES_BUCKET_URL}</endpoint>
<use_environment_credentials>true</use_environment_credentials>
</s3>
</disks>
</storage_configuration>
</clickhouse>このセクションでは、ClickHouse が頻繁に利用されないデータを保存するために使用できるリモート ディスク (DigitalOcean Space) を構成します。.
注意: 値 {YOUR_S3_SPACES_BUCKET_URL} をエンドポイント URL に置き換えます。.
ステップ4 - 階層型ストレージを備えたテーブルを作成する
ClickHouseで階層型ストレージを使用するテーブルを作成します。複数のストレージポリシーを指定して、どのデータをローカルディスクに保存し、どのデータをリモートディスク(Spaces)に保存するかを決定できます。.
指定された期間後に古いデータを DigitalOcean Spaces に移動する保持ポリシーを定義します。
CREATE TABLE IF NOT EXISTS tiered_logs (
event_time DateTime,
level String,
message String
) ENGINE = MergeTree
ORDER BY (event_time)
TTL toDateTime(event_time) + INTERVAL 2 MINUTE TO VOLUME 'cold'
SETTINGS storage_policy = 's3_tiered';説明:
- デフォルト: これは、最近または頻繁に使用されるデータが保存されるローカル ディスク ストレージです。.
- s3: 古いデータが移動されるリモート ストレージ (DigitalOcean Spaces) です。.
この構成により、新しいデータがローカル ディスクに書き込まれ、古いデータは DigitalOcean Spaces に自動的に移行されます。.
ステップ5 - ClickHouseサーバーを実行する
ClickHouse サーバーを起動するには、次のコマンドを実行します。
docker build -t clickhouse-demo .
docker run -d --name clickhouse-demo -p 8123:8123 -p 9000:9000 clickhouse-demoネットワークポート
- 8123: これは、HTTPインターフェース経由でClickHouseと通信するために使用されるHTTPポートです。(http://localhost:8123/play)。このポートは、ブラウザやcurl、PostmanなどのコマンドラインツールからSQLクエリを実行するために使用できます。このポートは、HTTP経由でClickHouseと通信するWebアプリケーションやクライアントでよく使用されます。.
- 9000: この TCP ポートは、ClickHouse クライアントとサーバーがメイン ClickHouse プロトコルを使用して相互に通信するためのメイン ポートです。.
- 参考: https://clickhouse.com/docs/en/guides/sre/network-ports
以下を使用して検証:
docker ps
ステップ6 - ログを送信する簡単なGoプログラムを実行する
新しいフォルダに、 メイン.go ClickHouse にログを送信するものを作成します。.
package main
import (
"database/sql"
"fmt"
"log"
"os"
"time"
"github.com/ClickHouse/clickhouse-go"
"github.com/sirupsen/logrus"
)
type ClickHouseHook struct {
db *sql.DB
entries []logrus.Entry
batchSize int
}
// NewClickHouseHook establishes a connection to ClickHouse using the provided DSN.
func NewClickHouseHook(dsn string, batchSize int) (*ClickHouseHook, error) {
db, err := sql.Open("clickhouse", dsn)
if err != nil {
return nil, err
}
if err := db.Ping(); err != nil {
if exception, ok := err.(*clickhouse.Exception); ok {
log.Fatalf("[%d] %s \n%s\n", exception.Code, exception.Message, exception.StackTrace)
} else {
log.Fatal(err)
}
}
return &ClickHouseHook{db: db, batchSize: batchSize}, nil
}
// Fire is triggered by Logrus to log entries to ClickHouse.
func (hook *ClickHouseHook) Fire(entry *logrus.Entry) error {
hook.entries = append(hook.entries, *entry)
if len(hook.entries) >= hook.batchSize {
if err := hook.flush(); err != nil {
return err
}
}
return nil
}
// flush sends the collected log entries to ClickHouse in a batch.
func (hook *ClickHouseHook) flush() error {
tx, err := hook.db.Begin()
if err != nil {
return err
}
stmt, err := tx.Prepare("INSERT INTO tiered_logs (event_time, level, message) VALUES (?, ?, ?)")
if err != nil {
return err
}
defer stmt.Close()
for _, entry := range hook.entries {
if _, err := stmt.Exec(entry.Time, entry.Level.String(), entry.Message); err != nil {
return err
}
}
if err := tx.Commit(); err != nil {
return err
}
// Clear the entries after flushing
hook.entries = nil
return nil
}
// Levels returns the logging levels for which the hook is triggered.
func (hook *ClickHouseHook) Levels() []logrus.Level {
return logrus.AllLevels
}
func main() {
// ClickHouse DSN (replace with your credentials and host)
dsn := "tcp://localhost:9000?database=default&username=default&password=&debug=true"
// Create ClickHouse hook with a batch size of 5
hook, err := NewClickHouseHook(dsn, 5)
if err != nil {
log.Fatalf("failed to connect to ClickHouse: %v", err)
}
defer hook.db.Close()
// Set up logrus
logger := logrus.New()
logger.Out = os.Stdout
logger.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
})
logger.AddHook(hook)
// Log some entries
for i := 0; i < 10; i++ {
logger.WithFields(logrus.Fields{
"iteration": i,
}).Info("This is an info log entry")
time.Sleep(time.Second)
}
// Flush any remaining log entries before exiting
if err := hook.flush(); err != nil {
log.Fatalf("failed to flush logs to ClickHouse: %v", err)
}
fmt.Println("Logs sent to ClickHouse.")
}パッケージの依存関係をインストールするには:
go mod init example.com/clickhouse-logging
go get github.com/ClickHouse/clickhouse-go
go get github.com/sirupsen/logrusアプリケーションを実行するには:
go run main.goステップ7 — 結果を確認する
ClickHouse クライアントを起動するには、次のコマンドを実行します。
docker exec -it clickhouse-demo clickhouse-clientClickHouse クラスターのログを確認するには:
SELECT * FROM tiered_logsこのログ エントリのストレージ ディスクを調べると、それがデフォルト (ローカル) ディスク (ホット ストレージとも呼ばれます) に保存されていることがわかります。.
SELECT name, disk_name FROM system.parts WHERE table = 'tiered_logs';
CREATE TABLE クエリで指定された 2 分間隔が経過すると、これらのレポートが S3 ディスク (リモート バケット/スペース) (コールド ストレージとも呼ばれます) に移動されていることを確認できます。.
DigitalOcean Cloud UI で、バケットにデータが含まれていることも確認できます。
結果
このガイドに従うことで、ClickHouseの階層型ストレージオプションとしてDigitalOcean Spacesを設定することができました。この構成により、アクセス頻度の低いデータをコスト効率の高いオブジェクトストレージに移動することでストレージコストを最適化し、パフォーマンスを向上させると同時に、アクティブなデータ用の高性能ストレージを維持できます。.























