مقدمة
ClickHouse هو نظام إدارة قواعد بيانات عمودية مفتوح المصدر، يتميز بأداء ممتاز في إجراء استعلامات OLAP عالية الأداء وتحليلات آنية. مع ذلك، قد يكون توسيع نطاق تخزين البيانات في ClickHouse أمرًا صعبًا، خاصةً مع تزايد أحجام البيانات. أحد الحلول الفعالة هو استخدام التخزين المتدرج، الذي يسمح بنقل البيانات التي لا يتم الوصول إليها بشكل متكرر إلى مساحة تخزين أكثر فعالية من حيث التكلفة، مع الاحتفاظ بالبيانات التي يتم الوصول إليها بشكل متكرر على مساحة تخزين أسرع وأكثر تكلفة. يدعم ClickHouse مجموعة متنوعة من منصات تخزين البيانات الخلفية، بما في ذلك الأقراص المحلية والخيارات البعيدة مثل مساحات DigitalOcean. عند إدارة كميات كبيرة من البيانات، من الشائع استخدام أجهزة تخزين متعددة.
DigitalOcean Spaces هي خدمة تخزين كائنات يمكن دمجها كطبقة ضمن بنية التخزين المتدرجة ClickHouse. سيرشدك هذا الدليل إلى خطوات تهيئة DigitalOcean Spaces كخيار تخزين متدرج لمجموعة ClickHouse الخاصة بك.
في هذا الدليل، سنقوم بإعداد تطبيق Go بسيط يُرسل سجلات دفعية إلى ClickHouse. أولًا، تُخزَّن السجلات في وحدة تخزين ساخنة (القرص الافتراضي، ويُسمى أيضًا محليًا)، ثم بعد فترة زمنية محددة (دقيقتان)، تُنقل إلى وحدة تخزين باردة (مثل وحدة تخزين S3 مثل DO Spaces).
المتطلبات الأساسية
قبل أن تبدأ، تأكد من أن لديك ما يلي:
- حساب سحابي على DigitalOcean.
- دلو DigitalOcean Spaces.
- مفاتيح الوصول إلى DigitalOcean Spaces.
- مقدمة أساسية لتكوينات ClickHouse وتخزين الكائنات.
الخطوة 1 - إنشاء وتكوين مساحة DigitalOcean
سجّل دخولك إلى حسابك على DigitalOcean Cloud وأنشئ مساحة (دلوًا) جديدة. سيُستخدم هذا الدلو كمساحة تخزين متدرجة للبيانات التي نادرًا ما يتم الوصول إليها.
- انتقل إلى قسم المساحات في لوحة المعلومات.
- انقر فوق "إنشاء مساحة جديدة"، وأدخل اسمًا، وحدد منطقة، ثم اضبط الأذونات.
- لاحظ عنوان URL لنقطة النهاية.
- قم بتدوين مفتاح الوصول والمفتاح السري لأنك ستحتاج إليهما في الخطوات التالية.
في هذه المرحلة، تم إنشاء دلوك وأصبح جاهزًا للتكامل مع ClickHouse.
الخطوة 2 - إعداد خادم ClickHouse في حاوية Docker
للبدء، قم بإنشاء مجلد وأطلق عليه اسم "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 - تكوين ClickHouse للتخزين المتوافق مع S3
في هذه الخطوة، ستقوم بتكوين ClickHouse لاستخدام DigitalOcean Spaces كطبقة في نظام التخزين لديك. يتضمن ذلك إضافة تكوين التخزين إلى ملف config.xml في تثبيت ClickHouse.
لاستخدام دلو 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>يقوم هذا القسم بتكوين قرص بعيد (مساحة DigitalOcean) يمكن لـ ClickHouse استخدامه لتخزين البيانات المتوفرة بشكل غير متكرر.
ملاحظة: استبدل القيم {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) حيث يتم نقل البيانات القديمة.
يضمن هذا التكوين كتابة البيانات الجديدة على القرص المحلي ونقل البيانات القديمة تلقائيًا إلى 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). يُمكنك استخدام هذا المنفذ لتشغيل استعلامات SQL عبر المتصفح أو من خلال أدوات سطر الأوامر مثل curl أو Postman. ويُستخدم غالبًا لتطبيقات الويب أو العملاء الذين يتفاعلون مع ClickHouse عبر HTTP.
- 9000: يعد منفذ TCP هذا المنفذ الرئيسي لعملاء وخوادم ClickHouse للتواصل مع بعضهم البعض باستخدام بروتوكول ClickHouse الرئيسي.
- المرجع: https://clickhouse.com/docs/en/guides/sre/network-ports
التحقق باستخدام:
docker ps
الخطوة 6 - تشغيل برنامج Go بسيط يرسل السجلات
في مجلد جديد، ملف يسمى main.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-clientللتحقق من السجلات في مجموعة ClickHouse:
SELECT * FROM tiered_logsعند فحص قرص التخزين بحثًا عن إدخال السجل هذا، نرى أنه تم تخزينه على القرص الافتراضي (المحلي) - المعروف أيضًا باسم التخزين الساخن.
SELECT name, disk_name FROM system.parts WHERE table = 'tiered_logs';
بعد الفاصل الزمني لمدة دقيقتين المحدد في استعلام CREATE TABLE، يمكنك التحقق من نقل هذه التقارير إلى أقراص S3 (دلو/مساحة بعيدة) - والتي تسمى أيضًا التخزين البارد.
يمكننا أيضًا أن نرى في واجهة مستخدم DigitalOcean Cloud أن دلونا يحتوي الآن على بيانات:
نتيجة
باتباع هذا الدليل، تكون قد نجحت في تهيئة DigitalOcean Spaces كخيار تخزين متعدد الطبقات لـ ClickHouse. يتيح لك هذا التهيئة تحسين تكاليف التخزين والأداء من خلال نقل البيانات التي لا يتم الوصول إليها بشكل متكرر إلى تخزين كائني فعال من حيث التكلفة، مع الحفاظ على تخزين عالي الأداء للبيانات النشطة.























