ClickHouse Kafka Connect Sink هو موصل لـ Kafka ينقل البيانات من Kafka موضوع إلى ClickHouse table.
الترخيص
يُوزَّع Kafka Connector Sink بموجب ترخيص Apache 2.0
متطلبات البيئة
يجب أن يكون إطار عمل Kafka Connect بالإصدار 2.7 أو أحدث مثبّتًا في البيئة، وأن يعمل على Java 11 أو أحدث.
مصفوفة توافق الإصدارات
| إصدار ClickHouse Kafka Connect | إصدار ClickHouse | Kafka Connect | Confluent Platform | عميل Java لـ ClickHouse |
|---|---|---|---|---|
| 1.4.x (الأحدث) | 23.3+ | 2.7+ | 6.1+ | 0.9.5 |
| 1.3.x | 23.3+ | 2.7+ | 6.1+ | 0.8.0 إلى 0.9.5 |
| 1.2.x | 23.3+ | 2.7+ | 6.1+ | 0.6.3 إلى 0.8.0 |
| 1.1.x | 23.3+ | 2.7+ | 6.1+ | 0.6.0 إلى 0.6.1 |
| 1.0.x | 23.3+ | 2.7+ | 6.1+ | 0.4.6 إلى 0.6.0 |
يرفض الموصل البدء عند استخدام خوادم ClickHouse بإصدار أقدم من 23.3. استخدم دائمًا أحدث إصدار، ما لم يكن لديك سبب لتثبيت إصدار أقدم.
الميزات الرئيسية
- يأتي مزوّدًا بضمانات exactly-once جاهزة للاستخدام. ويعتمد على ميزة أساسية جديدة في ClickHouse باسم KeeperMap (تُستخدم كمخزن للحالة بواسطة الموصل)، ما يتيح معمارية مبسطة للغاية.
- دعم مخازن الحالة التابعة لجهات خارجية: يستخدم حاليًا In-memory افتراضيًا، ويمكنه أيضًا استخدام KeeperMap (ستتم إضافة Redis قريبًا).
- تكامل أصيل: يطوّره ClickHouse ويتولى صيانته ودعمه.
- يُختبَر باستمرار على ClickHouse Cloud.
- يدعم إدراج البيانات بمخطط مُعلن أو بدون مخطط.
- يدعم جميع أنواع البيانات في ClickHouse.
إرشادات التثبيت
اجمع بيانات الاتصال الخاصة بك
للاتصال بـ ClickHouse باستخدام HTTP(S)، تحتاج إلى المعلومات التالية:
| المعلمات | الوصف |
|---|---|
HOST and PORT |
عادةً ما يكون المنفذ 8443 عند استخدام TLS، أو 8123 عند عدم استخدام TLS. |
DATABASE NAME |
افتراضيًا، توجد قاعدة بيانات باسم default. استخدم اسم قاعدة البيانات التي تريد الاتصال بها. |
USERNAME and PASSWORD |
افتراضيًا، يكون اسم المستخدم default. استخدم اسم المستخدم المناسب لحالة الاستخدام لديك. |
تتوفر تفاصيل خدمة ClickHouse Cloud الخاصة بك في ClickHouse Cloud console. حدِّد خدمة ثم انقر على Connect:

اختر HTTPS. ستظهر تفاصيل الاتصال في مثال لأمر curl.

إذا كنت تستخدم ClickHouse مُدارًا ذاتيًا، فسيُحدِّد مسؤول ClickHouse لديك تفاصيل الاتصال.
إرشادات التثبيت العامة
يُوزَّع هذا الموصل على هيئة ملف JAR واحد يحتوي على جميع ملفات الفئات اللازمة لتشغيل المكوّن الإضافي.
لتثبيت المكوّن الإضافي، اتبع الخطوات التالية:
- نزّل أرشيف ZIP يحتوي على ملف JAR الخاص بالموصل من صفحة Releases في مستودع ClickHouse Kafka Connect Sink.
- استخرج محتويات ملف ZIP وانسخها إلى الموقع المطلوب.
- أضف path يتضمن دليل المكوّن الإضافي إلى إعداد plugin.path في ملف خصائص Connect للسماح لـ Confluent Platform بالعثور على المكوّن الإضافي.
- وفّر اسم الموضوع وhostname الخاص بـ ClickHouse instance وpassword في config.
connector.class=com.clickhouse.kafka.connect.ClickHouseSinkConnector
tasks.max=1
topics=<topic_name>
ssl=true
jdbcConnectionProperties=?sslmode=STRICT
security.protocol=SSL
hostname=<hostname>
database=<database_name>
password=<password>
ssl.truststore.location=/tmp/kafka.client.truststore.jks
port=8443
value.converter.schemas.enable=false
value.converter=org.apache.kafka.connect.json.JsonConverter
exactlyOnce=true
username=default
schemas.enable=false- أعد تشغيل Confluent Platform.
- إذا كنت تستخدم Confluent Platform، فسجّل الدخول إلى واجهة المستخدم الخاصة بـ Confluent Control Center للتحقق من أن ClickHouse Sink متاح في قائمة الموصلات المتاحة.
خيارات التهيئة
لربط ClickHouse Sink بخادم ClickHouse، يلزم توفير ما يلي:
- تفاصيل الاتصال: اسم المضيف (مطلوب) والمنفذ (اختياري)
- بيانات اعتماد المستخدم: كلمة المرور (مطلوب) واسم المستخدم (اختياري)
- فئة الموصّل:
com.clickhouse.kafka.connect.ClickHouseSinkConnector(مطلوب) topicsأوtopics.regex: مواضيع Kafka التي سيقرأها الموصّل — يجب أن تتطابق أسماء المواضيع مع أسماء الجداول (مطلوب)- محوّلات المفتاح والقيمة: اضبطها بناءً على نوع البيانات في الموضوع لديك. وهي مطلوبة إذا لم تكن معرّفة مسبقًا في إعدادات العامل.
الجدول الكامل لخيارات التهيئة:
| اسم الخاصية | الوصف | القيمة الافتراضية |
|---|---|---|
hostname (مطلوب) |
اسم المضيف أو عنوان IP للخادم | غير متاح |
port |
منفذ ClickHouse — القيمة الافتراضية هي 8443 (لـ HTTPS في Cloud)، ولكن بالنسبة إلى HTTP (وهو الافتراضي في بيئات self-hosted) فيجب أن يكون 8123 | 8443 |
ssl |
تمكين اتصال SSL بـ ClickHouse | true |
jdbcConnectionProperties |
خصائص الاتصال عند الاتصال بـ ClickHouse. يجب أن تبدأ بـ ?، وأن تُفصل المعلمات باستخدام & بصيغة param=value |
"" |
username |
اسم مستخدم قاعدة بيانات ClickHouse | default |
password (إلزامي) |
كلمة مرور قاعدة بيانات ClickHouse | غير متاح |
database |
اسم قاعدة بيانات ClickHouse | default |
connector.class (مطلوب) |
فئة الموصل (عيّنها صراحةً واتركها بالقيمة الافتراضية) | "com.clickhouse.kafka.connect.ClickHouseSinkConnector" |
tasks.max |
عدد مهام الموصل | "1" |
errors.retry.timeout |
الحد الأقصى لمدة إعادة المحاولة في Kafka Connect بالمللي ثانية. 0 يعني عدم إجراء أي إعادة محاولات. -1 يعني إعادة محاولات غير محدودة. القيمة الموصى بها هي أكثر من "10000" مللي ثانية (10 ثوانٍ) مهلة |
"0" |
exactlyOnce |
تمكين exactly-once | "false" |
topics (مطلوب) |
موضوعات Kafka المطلوب جلبها - يجب أن تتطابق أسماء الموضوعات مع أسماء الجداول | "" |
key.converter (مطلوب* - راجع الوصف) |
يُضبط وفقًا لأنواع مفاتيحك. ويكون مطلوبًا هنا إذا كنت تمرّر مفاتيح (ولم تكن مُعرّفة في إعدادات العامل). | "org.apache.kafka.connect.storage.StringConverter" |
value.converter (مطلوب* - راجع الوصف) |
يُضبط بناءً على نوع البيانات في الـ topic لديك. التنسيقات المدعومة: - JSON وString وAvro وProtobuf. ويكون مطلوبًا هنا إذا لم يكن مُعرّفًا في إعدادات العامل. | "org.apache.kafka.connect.json.JsonConverter" |
value.converter.schemas.enable |
دعم المخطط لمحوّل القيمة في الموصل | "false" |
errors.tolerance |
تحمّل أخطاء الموصل. القيم المدعومة: none, all | "none" |
errors.deadletterqueue.topic.name |
إذا تم تعيينه (مع errors.tolerance=all)، فستُستخدَم DLQ للدفعات التي فشلت (راجع استكشاف الأخطاء وإصلاحها) | "" |
errors.deadletterqueue.context.headers.enable |
يضيف headers إضافية إلى DLQ | "" |
clickhouseSettings |
قائمة مفصولة بفواصل من إعدادات ClickHouse (مثلًا: "insert_quorum=2, etc…") | "" |
topic2TableMap |
قائمة مفصولة بفواصل تربط أسماء الـ topic بأسماء الجداول (مثلًا: "topic1=table1, topic2=table2, etc…") | "" |
tableRefreshInterval |
المدة (بالثواني) اللازمة لتحديث cache تعريف الجدول | 0 |
keeperOnCluster |
يتيح تهيئة المعلمة ON CLUSTER للمثيلات ذاتية الاستضافة (على سبيل المثال، ON CLUSTER clusterNameInConfigFileDefinition) لجدول connect_state الخاص بـ exactly-once (راجع استعلامات DDL الموزعة |
"" |
bypassRowBinary |
يتيح تعطيل استخدام RowBinary وRowBinaryWithDefaults للبيانات المستندة إلى مخطط (Avro وProtobuf وما إلى ذلك) — ويجب استخدامه فقط عندما تحتوي البيانات على أعمدة مفقودة، ولا يكون Nullable/Default خيارًا مقبولًا | "false" |
dateTimeFormats |
تنسيقات التاريخ والوقت لتحليل حقول المخطط من نوع DateTime64، مفصولة بعلامة ; (على سبيل المثال: someDateField=yyyy-MM-dd HH:mm:ss.SSSSSSSSS;someOtherDateField=yyyy-MM-dd HH:mm:ss). |
"" |
tolerateStateMismatch |
يسمح للموصل بتجاهل السجلات "الأقدم" من الإزاحة الحالية المخزنة في AFTER_PROCESSING (على سبيل المثال، إذا أُرسلت الإزاحة 5 وكانت الإزاحة 250 هي آخر إزاحة مسجَّلة). ينبغي استخدامه لإصلاح إدخال البيانات بعد حدوث فشل، ثم يجب إعادته إلى "false" بعد الانتهاء. |
"false" |
ignorePartitionsWhenBatching |
سيُتجاهل الـ partition عند تجميع الرسائل من أجل insert (ولكن فقط إذا كانت exactlyOnce تساوي false). ملاحظة حول الأداء: كلما زاد عدد مهام الـ connector، انخفض عدد Kafka partitions المخصّصة لكل مهمة — ما قد يؤدي إلى تراجع العائد. |
"false" |
bufferCount (اعتبارًا من v1.3.6) |
عدد السجلات المطلوب تخزينها مؤقتًا في الذاكرة قبل إرسالها إلى ClickHouse. تؤدي القيمة 0 إلى تعطيل التخزين المؤقت الداخلي. لا يُدعم التخزين المؤقت عند استخدام exactlyOnce=true. |
"0" |
bufferFlushTime (اعتبارًا من v1.3.6) |
الحد الأقصى للوقت، بالملي ثانية، لتخزين السجلات مؤقتًا قبل التفريغ عندما يكون exactlyOnce=false. تؤدي القيمة 0 إلى تعطيل التفريغ المستند إلى الوقت. القيمة الافتراضية هي 0. مطلوب فقط لعتبة زمنية. ويكون فعالًا فقط عندما يكون bufferCount > 0. |
"0" |
reportInsertedOffsets (اعتبارًا من الإصدار v1.3.6) |
يتيح إرجاع الإزاحات التي نجح إدراجها فقط من preCommit (بدلًا من currentOffsets) عندما يكون exactlyOnce=false. ولا ينطبق ذلك عندما يكون ignorePartitionsWhenBatching=true، إذ تظل currentOffsets هي المُعادة. |
"false" |
client_version (اعتبارًا من v1.2.0) |
يحدد ClickHouse Java client الذي يستخدمه الموصل. القيم الصالحة هي "V1" و"V2". |
"V1" |
الجداول المستهدفة
يقرأ ClickHouse Connect Sink الرسائل من موضوعات Kafka ويكتبها إلى الجداول المناسبة. ويكتب ClickHouse Connect Sink البيانات إلى الجداول الموجودة مسبقًا. يُرجى التأكد من إنشاء جدول مستهدف ذي مخطط مناسب في ClickHouse قبل البدء في إدراج البيانات فيه.
يتطلب كل موضوع في Kafka جدولًا مستهدفًا مخصصًا في ClickHouse. يجب أن يتطابق اسم الجدول المستهدف مع اسم موضوع المصدر.
المعالجة المسبقة
إذا كنت بحاجة إلى تحويل الرسائل الصادرة قبل إرسالها إلى ClickHouse Kafka Connect Sink، فاستخدم تحويلات Kafka Connect.
أنواع البيانات المدعومة
مع تعريف مخطط:
| Kafka Connect Type | نوع ClickHouse | مدعوم | بدائي |
|---|---|---|---|
| STRING | String | ✅ | نعم |
| STRING | JSON. انظر أدناه (1) | ✅ | نعم |
| INT8 | Int8 | ✅ | نعم |
| INT16 | Int16 | ✅ | نعم |
| INT32 | Int32 | ✅ | نعم |
| INT64 | Int64 | ✅ | نعم |
| FLOAT32 | Float32 | ✅ | نعم |
| FLOAT64 | Float64 | ✅ | نعم |
| BOOLEAN | Boolean | ✅ | نعم |
| ARRAY | Array(T) | ✅ | لا |
| MAP | Map(Primitive, T) | ✅ | لا |
| STRUCT | Variant(T1, T2, …) | ✅ | لا |
| STRUCT | Tuple(a T1, b T2, …) | ✅ | لا |
| STRUCT | Nested(a T1, b T2, …) | ✅ | لا |
| STRUCT | JSON. انظر أدناه (1)، (2) | ✅ | لا |
| BYTES | String | ✅ | لا |
| org.apache.kafka.connect.data.Time | Int64 / DateTime64 | ✅ | لا |
| org.apache.kafka.connect.data.Timestamp | Int32 / Date32 | ✅ | لا |
| org.apache.kafka.connect.data.Decimal | Decimal | ✅ | لا |
-
(1) - لا يكون JSON مدعومًا إلا عندما تتضمن ClickHouse settings القيمة
input_format_binary_read_json_as_string=1. ولا يعمل ذلك إلا مع عائلة تنسيقات RowBinary format، كما يؤثر هذا الإعداد في جميع الأعمدة ضمن طلب insert، لذا يجب أن تكون كلها من نوع سلسلة نصية. في هذه الحالة، سيحوّل موصل قيمة STRUCT إلى JSON string. -
(2) - عندما يحتوي struct على unions مثل
oneof، يجب تهيئة converter بحيث لا يضيف prefix/suffix إلى أسماء الحقول. يتوفر الإعدادgenerate.index.for.unions=falseلـProtobufConverter.
من دون تعريف مخطط:
يُحوَّل السجل إلى JSON ويُرسَل إلى ClickHouse كقيمة بتنسيق JSONEachRow.
وصفات التهيئة
فيما يلي بعض وصفات التهيئة الشائعة لمساعدتك على البدء بسرعة.
التهيئة الأساسية
هذه أبسط تهيئة للبدء. وهي تفترض أنك تشغّل Kafka Connect في الوضع الموزّع، وأن لديك خادم ClickHouse يعمل على localhost:8443 مع تمكين SSL، وأن البيانات بتنسيق JSON بلا مخطط.
{
"name": "clickhouse-connect",
"config": {
"connector.class": "com.clickhouse.kafka.connect.ClickHouseSinkConnector",
"tasks.max": "1",
"consumer.override.max.poll.records": "5000",
"consumer.override.max.partition.fetch.bytes": "5242880",
"database": "default",
"errors.retry.timeout": "60000",
"exactlyOnce": "false",
"hostname": "localhost",
"port": "8443",
"ssl": "true",
"jdbcConnectionProperties": "?ssl=true&sslmode=strict",
"username": "default",
"password": "<PASSWORD>",
"topics": "<TOPIC_NAME>",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"clickhouseSettings": ""
}
}تهيئة أساسية مع موضوعات متعددة
يمكن للموصل استهلاك البيانات من عدة موضوعات
{
"name": "clickhouse-connect",
"config": {
"connector.class": "com.clickhouse.kafka.connect.ClickHouseSinkConnector",
...
"topics": "SAMPLE_TOPIC, ANOTHER_TOPIC, YET_ANOTHER_TOPIC",
...
}
}تهيئة أساسية مع DLQ
{
"name": "clickhouse-connect",
"config": {
"connector.class": "com.clickhouse.kafka.connect.ClickHouseSinkConnector",
...
"errors.tolerance": "all",
"errors.deadletterqueue.topic.name": "<DLQ_TOPIC>",
"errors.deadletterqueue.context.headers.enable": "true",
}
}دعم مخططات Avro
{
"name": "clickhouse-connect",
"config": {
"connector.class": "com.clickhouse.kafka.connect.ClickHouseSinkConnector",
...
"value.converter": "io.confluent.connect.avro.AvroConverter",
"value.converter.schema.registry.url": "<SCHEMA_REGISTRY_HOST>:<PORT>",
"value.converter.schemas.enable": "true",
}
}تعيين أنواع Avro
تُحدَّد تعيين الأنواع أدناه بواسطة io.confluent.connect.avro.AvroConverter، وهو التنفيذ الرسمي لتسلسل/إلغاء تسلسل Avro في Kafka Connect. راجع وثائق Kafka Connect للحصول على معلومات متقدمة حول منطق التحويل.
✅: مدعوم
❌: غير مدعوم
️⚠️: مدعوم جزئيًا
| نوع Avro | نوع Kafka Connect | مدعوم | ملاحظات |
|---|---|---|---|
| null | N/A | ❌ | غير مدعوم كنوع مستقل، لكن يمكن استخدامه ضمن اتحادات |
| boolean | BOOLEAN | ✅ | |
| int | INT8/INT16/INT32 | ✅ | القيمة الافتراضية هي INT32. ويُحوَّل إلى INT8 إذا كان المخطط يحتوي على الخاصية connect.type=int8 (وبالمثل إلى INT16 إذا كانت connect.type=int16) |
| long | INT64 | ✅ | |
| float | FLOAT32 | ✅ | |
| double | FLOAT64 | ✅ | |
| bytes | BYTES | ✅ | |
| string | STRING | ✅ | |
| record | STRUCT | ✅ | |
| enum | STRING | ✅ | |
| array | ARRAY/MAP | ✅ | القيمة الافتراضية هي ARRAY. ويُحوَّل إلى MAP إذا كان الحقل قد أُنشئ أصلًا عبر AvroData.fromConnectSchema (المصدر) |
| map | MAP | ✅ | |
| union | STRUCT/<T> |
⚠️ | القيمة الافتراضية هي STRUCT. ويُحوَّل إلى النوع المفرد T في تعريف union إذا كانت flatten.singleton.unions=true (راجع الوثائق) |
| fixed | BYTES | ⚠️ | النوع المنطقي decimal مع Fixed غير مدعوم (انظر أدناه) |
ارجع إلى أنواع البيانات المدعومة للاطلاع على التعيين بين أنواع Kafka Connect وأنواع ClickHouse.
مخططات Avro غير المدعومة
مخططات Avro التالية غير مدعومة في الموصّل:
- النوع المنطقي
decimalالمبني علىfixed
{"name": "decimal_18_4", "type": "fixed", "size": 8, "logicalType": "decimal", "precision": 18, "scale": 4}- اتحادات تقبل NULL
{"name": "mixed_union", "type": ["null", "string", "int"], "default": null}- حقول اتحاد في السجلات
{
"name": "record_union",
"type": [
{
"type": "record",
"name": "TypeA",
"fields": [
{
"name": "label",
"type": "string"
}
]
},
{
"type": "record",
"name": "TypeB",
"fields": [
{
"name": "count",
"type": "int"
}
]
}
]
}دعم مخطط Protobuf
{
"name": "clickhouse-connect",
"config": {
"connector.class": "com.clickhouse.kafka.connect.ClickHouseSinkConnector",
...
"value.converter": "io.confluent.connect.protobuf.ProtobufConverter",
"value.converter.schema.registry.url": "<SCHEMA_REGISTRY_HOST>:<PORT>",
"value.converter.schemas.enable": "true",
}
}يرجى ملاحظة ما يلي: إذا واجهت مشكلات بسبب فئات مفقودة، فليست كل البيئات تتضمن محوّل Protobuf، وقد تحتاج إلى إصدار بديل من ملف JAR يتضمن التبعيات.
تعيين أنواع Protobuf
يُحدَّد تعيين الأنواع أدناه بواسطة io.confluent.connect.protobuf.ProtobufConverter، وهو التنفيذ الرسمي لتسلسل/إلغاء تسلسل Protobuf في Kafka Connect. راجع وثائق Kafka Connect للحصول على معلومات متقدمة حول منطق التحويل.
✅: مدعوم
❌: غير مدعوم
️⚠️: مدعوم جزئيًا
| نوع Protobuf | نوع Kafka Connect | نوع ClickHouse | مدعوم | ملاحظات |
|---|---|---|---|---|
| double | FLOAT64 | Float64 | ✅ | |
| float | FLOAT32 | Float32 | ✅ | |
| int32 | INT8/INT16/INT32 | Int32 | ✅ | القيمة الافتراضية هي INT32. ويُحوَّل إلى INT8 إذا كان المخطط يتضمن الخيار connect.type=int8 (وبالمثل إلى INT16 إذا كان connect.type=int16) |
| sint32 | INT8/INT16/INT32 | Int32 | ✅ | القيمة الافتراضية هي INT32. ويُحوَّل إلى INT8 إذا كان المخطط يتضمن الخيار connect.type=int8 (وبالمثل إلى INT16 إذا كان connect.type=int16) |
| sfixed32 | INT8/INT16/INT32 | Int32 | ✅ | القيمة الافتراضية هي INT32. ويُحوَّل إلى INT8 إذا كان المخطط يتضمن الخيار connect.type=int8 (وبالمثل إلى INT16 إذا كان connect.type=int16) |
| uint32 | INT64 | UInt32 | ✅ | |
| fixed32 | INT64 | UInt32 | ✅ | |
| int64 | INT64 | Int64 | ✅ | |
| uint64 | INT64 | UInt64 | ✅ | |
| sint64 | INT64 | Int64 | ✅ | |
| fixed64 | INT64 | UInt64 | ✅ | |
| sfixed64 | INT64 | Int64 | ✅ | |
| bool | BOOLEAN | Bool | ✅ | |
| string | STRING | String | ✅ | |
| bytes | BYTES | String | ✅ | |
| enum | INT32/STRING | Int32 | ✅ | القيمة الافتراضية هي STRING. ويُحوَّل إلى INT32 إذا كان int.for.enums=true (راجع وثائق schema registry) |
| message | STRUCT | Tuple / JSON | ⚠️ | راجع قسم المخططات غير المدعومة أدناه |
| repeated T (where T is not a map entry) | ARRAY | Array(T) | ✅ | |
map<K, V> |
MAP | Map(K, V) | ✅ | |
| oneof | STRUCT | Tuple / Variant | ⚠️ | راجع القسم أدناه حول ترجمة oneof إلى مخطط ClickHouse |
| google.protobuf.DoubleValue | FLOAT64 | Nullable(Float64) | ✅ | |
| google.protobuf.FloatValue | FLOAT32 | Nullable(Float32) | ✅ | |
| google.protobuf.Int64Value | INT64 | Nullable(Int64) | ✅ | |
| google.protobuf.UInt64Value | INT64 | Nullable(UInt64) | ✅ | |
| google.protobuf.UInt32Value | INT64 | Nullable(UInt32) | ✅ | |
| google.protobuf.Int32Value | INT32 | Nullable(Int32) | ✅ | |
| google.protobuf.BoolValue | BOOLEAN | Nullable(Bool) | ✅ | |
| google.protobuf.StringValue | STRING | Nullable(String) | ✅ | |
| google.protobuf.BytesValue | BYTES | Nullable(String) | ✅ | |
| google.protobuf.Timestamp | org.apache.kafka.connect.data.Timestamp | DateTime64(3) | ✅ | |
| google.type.Date | org.apache.kafka.connect.data.Date | Date | ✅ | |
| google.type.TimeOfDay | org.apache.kafka.connect.data.Time | Int32 / Int64 | ✅ | |
| google.protobuf.Duration | STRUCT | Tuple(seconds Int64, nano Nullable(Int32)) |
✅ | |
| google.protobuf.Any | N/A | N/A | ❌ | |
| google.protobuf.Empty | N/A | N/A | ❌ |
ارجع إلى أنواع البيانات المدعومة للاطلاع على التعيين بين أنواع Kafka Connect وأنواع ClickHouse.
ملاحظة حول ترجمة حقول oneof إلى أعمدة ClickHouse
لا يدعم الموصّل ترجمة اتحادات في Protobuf (oneof) إلى النوع Variant في ClickHouse. وبدلًا من ذلك، أدرِج حقول oneof كحقول Nullable منفصلة في مخطط جدول ClickHouse لديك.
على سبيل المثال:
syntax = "proto3";
package com.clickhouse.kafka.connect.proto.test;
message StringIntUnion {
oneof mixed {
string mixed_string = 2;
int32 mixed_int = 3;
}
}ويُترجم إلى تعريف جدول ClickHouse التالي:
CREATE TABLE IF NOT EXISTS `StringIntUnion`
(
mixed_string Nullable(String),
mixed_int Nullable(Int32)
) ENGINE = ...;مخططات Protobuf غير المدعومة
مخططات Protobuf التالية غير مدعومة في الموصل:
- بُنى اتحاد متعددة الرسائل (قبل الإصدار 26.1 من CH)
syntax = "proto3";
package com.clickhouse.kafka.connect.proto.test;
message TwoRecords {
oneof payload {
TypeA type_a = 2;
TypeB type_b = 3;
}
// translates to Nullable(Tuple(label String)) in ClickHouse, which is unsupported
message TypeA {
string label = 1;
}
// translates to Nullable(Tuple(count Int32)) in ClickHouse, which is unsupported
message TypeB {
int32 count = 1;
}
}اعتبارًا من الإصدار 26.1 من CH وما بعده، أصبح هذا المخطط مدعومًا عند ضبط allow_experimental_nullable_tuple_type=1 (راجع صفحة التوثيق هذه).
دعم مخطط JSON
{
"name": "clickhouse-connect",
"config": {
"connector.class": "com.clickhouse.kafka.connect.ClickHouseSinkConnector",
...
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
}
}دعم String
يدعم الموصّل محوّل String في تنسيقات ClickHouse المختلفة: JSON، وCSV، وTSV.
{
"name": "clickhouse-connect",
"config": {
"connector.class": "com.clickhouse.kafka.connect.ClickHouseSinkConnector",
...
"value.converter": "org.apache.kafka.connect.storage.StringConverter",
"customInsertFormat": "true",
"insertFormat": "CSV"
}
}التخزين المؤقت الداخلي
يتيح التخزين المؤقت الداخلي لمهمة الـ sink تجميع السجلات من عدة استدعاءات poll() ثم flush لها إلى ClickHouse على شكل دفعات أكبر. ويمكن أن يحسّن ذلك الإنتاجية في أعباء العمل التي ينتج فيها كل استدعاء poll() العديد من الدفعات الصغيرة لكل partition.
السلوك الأساسي:
- يتحكم
bufferCountفي عدد السجلات التي تُخزَّن مؤقتًا قبل الـ flush. - يحدّد
bufferFlushTimeالحد الأقصى لوقت الانتظار (بالمللي ثانية) قبل عمل flush للسجلات المخزّنة مؤقتًا. - لا يكون
bufferFlushTimeفعّالًا إلا عندما تكونbufferCount > 0. - يُبقي
bufferCount=0وbufferFlushTime=0التخزين المؤقت معطّلًا (السلوك الافتراضي). - لا يكون التخزين المؤقت مدعومًا عندما تكون
exactlyOnce=true.
سبب عدم توافق التخزين المؤقت مع وضع exactly-once:
يؤدي التخزين المؤقت إلى تغيير حدود الدفعات، مما يعطّل إزالة تكرار كتل ClickHouse وآلة حالات الإزاحة الخاصة بالموصل.
ولحل ذلك، يمكنك إما تعطيل وضع exactly-once باستخدام exactlyOnce=false في config الخاص بالموصل، أو تعطيل التخزين المؤقت باستخدام bufferCount=0.
مثال:
{
"name": "clickhouse-connect",
"config": {
"connector.class": "com.clickhouse.kafka.connect.ClickHouseSinkConnector",
...
"exactlyOnce": "false",
"bufferCount": "5000",
"bufferFlushTime": "2000"
}
}التسجيل
يوفَّر التسجيل تلقائيًا بواسطة Kafka Connect Platform. يمكن تهيئة وجهة التسجيل وتنسيقه عبر ملف التهيئة الخاص بـ Kafka Connect.
إذا كنت تستخدم Confluent Platform، فيمكن عرض السجلات بتشغيل أمر من واجهة سطر الأوامر (CLI):
confluent local services connect logلمزيد من التفاصيل، راجع الدليل العملي.
المراقبة
يبلّغ ClickHouse Kafka Connect عن مقاييس وقت التشغيل عبر Java Management Extensions (JMX). ويكون JMX مفعّلًا في Kafka Connector بشكل افتراضي.
المقاييس الخاصة بـ ClickHouse
يوفّر الموصل مقاييس مخصّصة عبر اسم MBean التالي:
com.clickhouse:type=ClickHouseKafkaConnector,name=SinkTask{id}| اسم المقياس | النوع | الوصف |
|---|---|---|
receivedRecords |
long | العدد الإجمالي للسجلات المستلَمة. |
recordProcessingTime |
long | إجمالي الوقت بالنانوثانية المستغرَق في تجميع السجلات وتحويلها إلى بنية موحَّدة. |
taskProcessingTime |
long | إجمالي الوقت بالنانوثانية المستغرَق في معالجة البيانات وإدخالها إلى ClickHouse. |
مقاييس منتِج/مستهلك Kafka
يعرض الموصّل مقاييس Kafka القياسية الخاصة بالمنتِج والمستهلك، والتي توفّر رؤى حول تدفّق البيانات، ومعدل النقل، والأداء.
مقاييس على مستوى الموضوع:
records-sent-total: إجمالي عدد السجلات المُرسلة إلى الموضوعbytes-sent-total: إجمالي البايتات المُرسلة إلى الموضوعrecord-send-rate: متوسط معدل السجلات المُرسلة في الثانيةbyte-rate: متوسط عدد البايتات المُرسلة في الثانيةcompression-rate: نسبة الضغط المتحققة
مقاييس على مستوى الـ Partition:
records-sent-total: إجمالي السجلات المُرسلة إلى الـ partitionbytes-sent-total: إجمالي البايتات المُرسلة إلى الـ partitionrecords-lag: مقدار التأخر الحالي في الـ partitionrecords-lead: مقدار التقدّم الحالي في الـ partitionreplica-fetch-lag: معلومات التأخر الخاصة بالنسخ المتماثلة
مقاييس الاتصالات على مستوى العقدة:
connection-creation-total: إجمالي الاتصالات التي أُنشئت مع عقدة Kafkaconnection-close-total: إجمالي الاتصالات التي أُغلقتrequest-total: إجمالي الطلبات المُرسلة إلى العقدةresponse-total: إجمالي الاستجابات المستلمة من العقدةrequest-rate: متوسط معدل الطلبات في الثانيةresponse-rate: متوسط معدل الاستجابات في الثانية
تساعد هذه المقاييس في مراقبة ما يلي:
- معدل النقل: تتبّع معدلات إدخال البيانات
- التأخر: تحديد الاختناقات وتأخيرات المعالجة
- الضغط: قياس كفاءة ضغط البيانات
- سلامة الاتصال: مراقبة اتصال الشبكة واستقراره
مقاييس Kafka Connect Framework
يتكامل الموصل مع إطار عمل Kafka Connect ويعرض مقاييس لدورة حياة المهام وتتبع الأخطاء.
مقاييس حالة المهام:
task-count: العدد الإجمالي للمهام في الموصلrunning-task-count: عدد المهام قيد التشغيل حاليًاpaused-task-count: عدد المهام المتوقفة مؤقتًا حاليًاfailed-task-count: عدد المهام التي فشلتdestroyed-task-count: عدد المهام التي أُزيلتunassigned-task-count: عدد المهام غير المسندة
تشمل قيم حالة المهام: running وpaused وfailed وdestroyed وunassigned
مقاييس الأخطاء:
deadletterqueue-produce-failures: عدد عمليات الكتابة الفاشلة إلى DLQdeadletterqueue-produce-requests: إجمالي محاولات الكتابة إلى DLQlast-error-timestamp: الطابع الزمني لآخر خطأrecords-skip-total: العدد الإجمالي للسجلات التي جرى تخطيها بسبب الأخطاءrecords-retry-total: العدد الإجمالي للسجلات التي أُعيدت محاولتهاerrors-total: العدد الإجمالي للأخطاء التي تم رصدها
مقاييس الأداء:
offset-commit-failures: عدد حالات فشل تثبيت الإزاحةoffset-commit-avg-time-ms: متوسط وقت تثبيت الإزاحةoffset-commit-max-time-ms: أقصى وقت لتثبيت الإزاحةput-batch-avg-time-ms: متوسط وقت معالجة دفعةput-batch-max-time-ms: أقصى وقت لمعالجة دفعةsource-record-poll-total: إجمالي السجلات التي جرى سحبها
أفضل ممارسات المراقبة
- راقب تأخر المستهلك: تتبّع
records-lagلكل تقسيم لتحديد مواضع اختناق المعالجة - تتبّع معدلات الأخطاء: راقب
errors-totalوrecords-skip-totalلاكتشاف مشكلات جودة البيانات - راقب سلامة المهام: راقب مقاييس حالة المهام للتأكد من أنها تعمل على النحو الصحيح
- قِس معدل الإنتاجية: استخدم
records-send-rateوbyte-rateلتتبّع أداء الاستيعاب - راقب سلامة الاتصال: تحقّق من مقاييس الاتصال على مستوى العقدة لاكتشاف مشكلات الشبكة
- تتبّع كفاءة الضغط: استخدم
compression-rateلتحسين نقل البيانات
للاطلاع على تعريفات مقاييس JMX التفصيلية وتكامل Prometheus، راجع ملف الإعدادات jmx-export-connector.yml.
القيود
- عمليات الحذف غير مدعومة.
- يُورَّث حجم الدفعة من خصائص مستهلك Kafka.
- عند استخدام KeeperMap لتحقيق ضمان المعالجة مرة واحدة فقط وتغيير الإزاحة أو إرجاعها إلى قيمة سابقة، تحتاج إلى حذف المحتوى من KeeperMap لذلك الـموضوع المحدد. (راجع دليل استكشاف الأخطاء وإصلاحها أدناه لمزيد من التفاصيل)
ضبط الأداء وتحسين معدل النقل
يتناول هذا القسم استراتيجيات ضبط الأداء الخاصة بـ ClickHouse Kafka Connect Sink. ويُعد ضبط الأداء أمرًا أساسيًا عند التعامل مع حالات استخدام ذات معدل نقل مرتفع، أو عندما تحتاج إلى تحسين استخدام الموارد وتقليل زمن التأخر.
متى تكون هناك حاجة إلى ضبط الأداء؟
تكون هناك حاجة إلى ضبط الأداء عادةً في السيناريوهات التالية:
- أحمال العمل ذات معدل النقل المرتفع: عند معالجة ملايين الأحداث في الثانية من موضوعات Kafka
- تأخر المستهلك: عندما لا يتمكن الموصّل من مجاراة معدل إنتاج البيانات، مما يؤدي إلى زيادة التأخر
- قيود الموارد: عندما تحتاج إلى تحسين استخدام CPU أو الذاكرة أو الشبكة
- موضوعات متعددة: عند الاستهلاك من عدة موضوعات كبيرة الحجم في الوقت نفسه
- أحجام الرسائل الصغيرة: عند التعامل مع عدد كبير من الرسائل الصغيرة التي ستستفيد من التجميع على جانب الخادم
لا تكون هناك حاجة إلى ضبط الأداء عادةً عندما:
- تعالج أحجامًا منخفضة إلى متوسطة (< 10,000 رسالة/ثانية)
- يكون تأخر المستهلك مستقرًا ومقبولًا بالنسبة إلى حالة الاستخدام لديك
- تكون إعدادات الموصّل الافتراضية تلبي بالفعل متطلبات معدل النقل لديك
- يمكن لعنقود ClickHouse لديك التعامل بسهولة مع الحمل الوارد
فهم تدفق البيانات
قبل إجراء الضبط، من المهم فهم كيفية تدفق البيانات عبر الموصّل:
- يقوم Kafka Connect Framework بجلب الرسائل من موضوعات Kafka في الخلفية
- يستطلع الموصّل الرسائل من المخزن المؤقت الداخلي للإطار
- يجمّع الموصّل الرسائل استنادًا إلى حجم الاستطلاع
- يتلقى ClickHouse عملية الإدراج المجمّعة عبر HTTP/S
- يعالج ClickHouse عملية الإدراج (بشكل متزامن أو غير متزامن)
يمكن تحسين الأداء في كل مرحلة من هذه المراحل.
ضبط حجم الدُفعات في Kafka Connect
أول مستويات التحسين يتمثل في التحكم بكمية البيانات التي يتلقاها الموصل في كل دفعة من Kafka.
إعدادات الجلب
يجلب Kafka Connect (الإطار) الرسائل من موضوعات Kafka في الخلفية، بشكل مستقل عن الموصل:
fetch.min.bytes: الحد الأدنى لكمية البيانات قبل أن يمرّر الإطار القيم إلى الموصل (الافتراضي: 1 بايت)fetch.max.bytes: الحد الأقصى لكمية البيانات التي يمكن جلبها في طلب واحد (الافتراضي: 52428800 / 50 ميغابايت)fetch.max.wait.ms: الحد الأقصى لمدة الانتظار قبل إعادة البيانات إذا لم يتم استيفاءfetch.min.bytes(الافتراضي: 500 مللي ثانية)
إعدادات الاستطلاع
يجلب الموصّل الرسائل من المخزن المؤقت الخاص بإطار العمل عبر عملية استطلاع:
max.poll.records: الحد الأقصى لعدد السجلات المُعادة في عملية استطلاع واحدة (الافتراضي: 500)max.partition.fetch.bytes: الحد الأقصى لكمية البيانات لكل تقسيم (الافتراضي: 1048576 / 1 MB)
الإعدادات الموصى بها لمعدل النقل العالي
للحصول على أفضل أداء مع ClickHouse، احرص على استخدام دفعات أكبر:
# Increase the number of records per poll
consumer.override.max.poll.records=5000
# Increase the partition fetch size (5 MB)
consumer.override.max.partition.fetch.bytes=5242880
# Optional: Increase minimum fetch size to wait for more data (1 MB)
consumer.override.fetch.min.bytes=1048576
# Optional: Reduce wait time if latency is critical
consumer.override.fetch.max.wait.ms=300مهم: تمثل إعدادات الجلب في Kafka Connect بيانات مضغوطة، بينما يتلقى ClickHouse بيانات غير مضغوطة. وازن بين هذه الإعدادات وفقًا لنسبة الضغط لديك.
المفاضلات:
- دفعات أكبر = أداء أفضل لإدخال البيانات إلى ClickHouse، وأجزاء أقل، وعبء إضافي أقل
- دفعات أكبر = استخدام أعلى للذاكرة، واحتمال زيادة زمن الانتقال من البداية إلى النهاية
- دفعات كبيرة جدًا = خطر حدوث timeout، أو أخطاء OutOfMemory، أو تجاوز
max.poll.interval.ms
مزيد من التفاصيل: وثائق Confluent | وثائق Kafka
عمليات الإدراج غير المتزامنة
تُعد عمليات الإدراج غير المتزامنة ميزة فعّالة عندما يرسل الموصّل دفعات صغيرة نسبيًا، أو عندما تريد تحسين إدخال البيانات بشكل أكبر عبر إسناد مسؤولية التجميع إلى ClickHouse.
متى تستخدم عمليات الإدراج غير المتزامنة
فكّر في تمكين عمليات الإدراج غير المتزامنة عندما:
- العديد من الدُفعات الصغيرة: يرسل الموصّل دُفعات صغيرة ومتكررة (< 1000 صف لكل دفعة)
- تزامن مرتفع: تكتب مهام موصّل متعددة إلى الجدول نفسه
- نشر موزّع: تشغيل العديد من مثيلات الموصّل عبر مضيفين مختلفين
- عبء إضافي ناتج عن إنشاء الأجزاء: تواجه أخطاء "عدد كبير جدًا من الأجزاء"
- عبء عمل مختلط: الجمع بين استيعاب البيانات في الوقت الفعلي وأعباء عمل الاستعلامات
لا تستخدم عمليات الإدراج غير المتزامنة عندما:
- كنت ترسل بالفعل دُفعات كبيرة (> 10,000 صف لكل دفعة) بوتيرة مضبوطة
- كنت تحتاج إلى ظهور البيانات فورًا (يجب أن ترى الاستعلامات البيانات على الفور)
- كانت دلالات ضمان المعالجة مرة واحدة فقط مع
wait_for_async_insert=0تتعارض مع متطلباتك - كان سيناريو الاستخدام لديك سيستفيد بدلًا من ذلك من تحسينات التجميع على جهة العميل
كيف تعمل عمليات الإدراج غير المتزامنة
عند تمكين عمليات الإدراج غير المتزامنة، يقوم ClickHouse بما يلي:
- يستقبل استعلام الإدراج من الموصّل
- يكتب البيانات إلى مخزن مؤقت في الذاكرة (بدلًا من كتابتها إلى القرص فورًا)
- يعيد نجاح العملية إلى الموصّل (إذا كانت
wait_for_async_insert=0) - يفرّغ المخزن المؤقت إلى القرص عند تحقق أحد الشروط التالية:
- وصول المخزن المؤقت إلى
async_insert_max_data_size(القيمة الافتراضية: 100 MB) - انقضاء
async_insert_busy_timeout_msملّي ثانية منذ أول عملية إدراج (القيمة الافتراضية: 1000 ms) - بلوغ الحد الأقصى لعدد الاستعلامات المتراكمة (
async_insert_max_query_number، القيمة الافتراضية: 100)
- وصول المخزن المؤقت إلى
يقلل هذا بشكل كبير عدد الأجزاء التي يتم إنشاؤها ويحسّن معدل النقل الإجمالي.
تمكين async inserts
أضف إعدادات async insert إلى معلَمة التهيئة clickhouseSettings:
{
"name": "clickhouse-connect",
"config": {
"connector.class": "com.clickhouse.kafka.connect.ClickHouseSinkConnector",
...
"clickhouseSettings": "async_insert=1,wait_for_async_insert=1"
}
}الإعدادات الرئيسية:
async_insert=1: تمكين الإدراجات غير المتزامنةwait_for_async_insert=1(موصى به): ينتظر الموصل حتى تُفرَّغ البيانات إلى تخزين ClickHouse قبل إرسال الإقرار. يوفّر ضمانات للتسليم.wait_for_async_insert=0: يرسل الموصل الإقرار فورًا بعد التخزين المؤقت. يوفّر أداءً أفضل، لكن قد تُفقد البيانات إذا تعطّل الخادم قبل تفريغها.
ضبط سلوك async insert
يمكنك ضبط سلوك flush في async insert بدقة:
"clickhouseSettings": "async_insert=1,wait_for_async_insert=1,async_insert_max_data_size=104857600,async_insert_busy_timeout_ms=1000"معلمات الضبط الشائعة:
async_insert_max_data_size(الافتراضي: 104857600 / 100 MB): الحد الأقصى لحجم المخزن المؤقت قبل التفريغasync_insert_busy_timeout_ms(الافتراضي: 1000): الحد الأقصى للوقت (مللي ثانية) قبل التفريغasync_insert_stale_timeout_ms(الافتراضي: 0): الوقت (مللي ثانية) منذ آخر عملية إدراج قبل التفريغasync_insert_max_query_number(الافتراضي: 100): الحد الأقصى لعدد الاستعلامات قبل التفريغ
المفاضلات:
- الفوائد: أجزاء بيانات أقل، وأداء دمج أفضل، وعبء أقل على CPU، وتحسّن في معدل النقل عند ارتفاع التزامن
- اعتبارات: لا تصبح البيانات قابلة للاستعلام فورًا، مع زيادة طفيفة في زمن الوصول من البداية إلى النهاية
- المخاطر: فقدان البيانات عند تعطل الخادم إذا كانت قيمة
wait_for_async_insert=0، واحتمال زيادة الضغط على الذاكرة مع المخازن المؤقتة الكبيرة
الإدراجات غير المتزامنة مع ضمان المعالجة مرة واحدة فقط
عند استخدام exactlyOnce=true مع الإدراجات غير المتزامنة:
{
"config": {
"exactlyOnce": "true",
"clickhouseSettings": "async_insert=1,wait_for_async_insert=1"
}
}مهم: استخدم دائمًا wait_for_async_insert=1 مع exactly-once لضمان عدم تنفيذ عمليات commit للإزاحة إلا بعد حفظ البيانات بشكل دائم.
لمزيد من المعلومات حول async inserts، راجع وثائق ClickHouse الخاصة بـ async inserts.
توازي الموصّل
زِد التوازي لتحسين معدل النقل:
المهام لكل موصل
"tasks.max": "4"تعالج كل مهمة مجموعة فرعية من أقسام موضوع. المزيد من المهام = مزيد من التوازي، ولكن:
- الحد الأقصى الفعّال لعدد المهام = عدد أقسام موضوع
- تحتفظ كل مهمة باتصالها الخاص بـ ClickHouse
- المزيد من المهام = عبء إضافي أكبر واحتمال أعلى لحدوث تنازع على الموارد
التوصية: ابدأ بتعيين tasks.max ليعادل عدد أقسام موضوع، ثم اضبطه بناءً على مقاييس CPU ومعدل النقل.
تجاهل الأقسام عند التجميع على دفعات
افتراضيًا، يجمع الموصل الرسائل على دفعات لكل قسم. ولزيادة معدل النقل، يمكنك التجميع على دفعات عبر الأقسام:
"ignorePartitionsWhenBatching": "true"** تحذير**: استخدم هذا فقط عندما يكون exactlyOnce=false. يمكن أن يحسّن هذا الإعداد معدل النقل من خلال إنشاء دفعات أكبر، لكنه يفقد ضمانات الترتيب داخل كل قسم.
عدة موضوعات عالية الإنتاجية
إذا كان موصل لديك مُعدًّا للاشتراك في عدة موضوعات، وكنت تستخدم topic2TableMap لربط الـ موضوعات بالجداول، وكنت تواجه اختناقًا عند الإدراج يؤدي إلى تأخر المستهلك، ففكّر في إنشاء موصل مستقل لكل موضوع بدلًا من ذلك.
يرجع السبب الرئيسي في ذلك إلى أن الدُفعات تُدرَج حاليًا في كل جدول بشكل تسلسلي.
التوصية: عند التعامل مع عدة موضوعات كبيرة الحجم، قم بنشر instance واحدة من موصل لكل موضوع لتحقيق أقصى معدل نقل متوازٍ لعمليات الإدراج.
اعتبارات محرّك جدول ClickHouse
اختر محرّك جدول ClickHouse المناسب لحالة الاستخدام لديك:
MergeTree: الأفضل لمعظم حالات الاستخدام، إذ يوازن بين أداء الاستعلام والإدراجReplicatedMergeTree: مطلوب لتحقيق التوفّر العالي، ويضيف عبئًا إضافيًا بسبب النسخ المتماثل*MergeTreeمعORDER BYمضبوط على نحو صحيح: حسّنه بما يلائم أنماط الاستعلام لديك
الإعدادات التي ينبغي مراعاتها:
CREATE TABLE my_table (...)
ENGINE = MergeTree()
ORDER BY (timestamp, id)
SETTINGS
-- Increase max insert threads for parallel part writing
max_insert_threads = 4,
-- Allow inserts with quorum for reliability (ReplicatedMergeTree)
insert_quorum = 2لإعدادات الإدراج على مستوى الموصّل:
"clickhouseSettings": "insert_quorum=2,insert_quorum_timeout=60000"تجميع الاتصالات والمهل الزمنية
يحتفظ الموصّل باتصالات HTTP مع ClickHouse. اضبط قيم المهلة للشبكات ذات زمن الاستجابة المرتفع:
"jdbcConnectionProperties": "?socket_timeout=300000,connection_timeout=30000"socket_timeout(الافتراضي: 30000 مللي ثانية): الحد الأقصى لمدة عمليات القراءةconnection_timeout(الافتراضي: 10000 مللي ثانية): الحد الأقصى للوقت اللازم لإنشاء الاتصال
ارفع هذه القيم إذا واجهت أخطاء انتهاء المهلة مع الدفعات الكبيرة.
مخزن الشبكة المؤقت للعميل
عند استخدام العميل V2 ("client_version": "V2")، تُنسخ البيانات بين المقبس وذاكرة التطبيق عبر مخزن مؤقت يتحكم فيه client_network_buffer_size (بالبايت). الحجم الافتراضي هو 300000 بايت. يمكن أن يؤدي استخدام مخزن مؤقت أكبر إلى تحسين معدل النقل عبر الوصلات ذات زمن الاستجابة المرتفع أو النطاق الترددي العالي، لكنه يزيد من استخدام الذاكرة لكل مهمة اتصال.
تُضبط جميع خيارات العميل عبر jdbcConnectionProperties بدلاً من clickhouseSettings. على سبيل المثال:
"jdbcConnectionProperties": "?client_network_buffer_size=1000000"إذا كنت بحاجة إلى ضبط عدة خصائص للعميل، فافصل بينها باستخدام &:
"jdbcConnectionProperties": "?ssl=true&client_network_buffer_size=1000000"مراقبة الأداء واستكشاف المشكلات
راقب هذه المقاييس الأساسية:
- Consumer lag: استخدم أدوات مراقبة Kafka لتتبّع التأخر في كل تقسيم
- مقاييس الموصل: راقب
receivedRecordsوrecordProcessingTimeوtaskProcessingTimeعبر JMX (راجع Monitoring) - مقاييس ClickHouse:
system.asynchronous_inserts: راقب استخدام المخزن المؤقت لعملية الإدراج غير المتزامنةsystem.parts: راقب عدد الأجزاء لاكتشاف مشكلات الدمجsystem.merges: راقب عمليات الدمج النشطةsystem.events: تتبّعInsertedRowsوInsertedBytesوFailedInsertQuery
مشكلات الأداء الشائعة:
| العَرَض | السبب المحتمل | الحل |
|---|---|---|
| ارتفاع Consumer lag | batches صغيرة جدًا | زِد max.poll.records، وفعّل عملية الإدراج غير المتزامنة |
| أخطاء "Too many parts" | inserts صغيرة ومتكررة | فعّل عملية الإدراج غير المتزامنة، وزِد حجم batch |
| أخطاء timeout | حجم batch كبير أو بطء الشبكة | قلّل حجم batch، وزِد socket_timeout، وتحقّق من الشبكة |
| ارتفاع CPU usage | عدد كبير جدًا من الأجزاء الصغيرة | فعّل عملية الإدراج غير المتزامنة، وزِد إعدادات الدمج |
| أخطاء OutOfMemory | حجم batch كبير جدًا | قلّل max.poll.records وmax.partition.fetch.bytes |
| حمل المهام غير متوازن | توزيع التقسيمات غير متوازن | أعد موازنة التقسيمات أو اضبط tasks.max |
ملخص أفضل الممارسات
- ابدأ بالإعدادات الافتراضية، ثم قِس واضبط استنادًا إلى الأداء الفعلي
- فضّل الدُفعات الأكبر: استهدف 10,000-100,000 صف لكل insert متى أمكن
- استخدم عمليات الإدراج غير المتزامنة عند إرسال الكثير من الدُفعات الصغيرة أو عند ارتفاع التزامن
- استخدم دائمًا
wait_for_async_insert=1مع ضمان المعالجة مرة واحدة فقط - وسّع أفقيًا: زِد
tasks.maxحتى يصل إلى عدد التقسيمات - موصل واحد لكل topic مرتفع الحجم لتحقيق أقصى إنتاجية
- راقب باستمرار: تتبّع تأخر المستهلك، وعدد الأجزاء، ونشاط الدمج
- اختبر جيدًا: اختبر دائمًا تغييرات التكوين تحت حمل واقعي قبل النشر في بيئة الإنتاج
مثال: إعداد لمعدل نقل عالٍ
فيما يلي مثال كامل مُحسَّن لمعدل نقل عالٍ:
{
"name": "clickhouse-high-throughput",
"config": {
"connector.class": "com.clickhouse.kafka.connect.ClickHouseSinkConnector",
"tasks.max": "8",
"topics": "high_volume_topic",
"hostname": "my-clickhouse-host.cloud",
"port": "8443",
"database": "default",
"username": "default",
"password": "<PASSWORD>",
"ssl": "true",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"exactlyOnce": "false",
"ignorePartitionsWhenBatching": "true",
"consumer.override.max.poll.records": "10000",
"consumer.override.max.partition.fetch.bytes": "5242880",
"consumer.override.fetch.min.bytes": "1048576",
"consumer.override.fetch.max.wait.ms": "500",
"clickhouseSettings": "async_insert=1,wait_for_async_insert=1,async_insert_max_data_size=16777216,async_insert_busy_timeout_ms=1000,socket_timeout=300000"
}
}هذا الإعداد:
- يعالج ما يصل إلى 10,000 سجل في كل عملية poll
- ينشئ batches عبر الأقسام للحصول على عمليات insert أكبر
- يستخدم عملية الإدراج غير المتزامنة مع buffer بسعة 16 ميغابايت
- يشغّل 8 tasks متوازية (طابقها مع عدد الأقسام لديك)
- مُحسَّن لتحقيق أعلى معدل النقل بدلًا من الالتزام الصارم بالترتيب
استكشاف الأخطاء وإصلاحها
"عدم تطابق الحالة للموضوع [someTopic] والتقسيم [0]"
يحدث هذا عندما تكون الإزاحة المخزنة في KeeperMap مختلفة عن الإزاحة المخزنة في Kafka، ويحدث ذلك عادةً عند حذف موضوع أو تعديل الإزاحة يدويًا. لإصلاح ذلك، ستحتاج إلى حذف القيم القديمة المخزنة لذلك الموضوع + التقسيم المحددين:
-- First, identify the database used to store the data.
SELECT * FROM [database].connect_state
-- Identify the key that matches the topic and partition.
ALTER TABLE [database].connect_state DELETE WHERE key = [keyname]"ما الأخطاء التي سيُعيد الموصل المحاولة معها؟"
ينصبّ التركيز حاليًا على تحديد الأخطاء العابرة التي يمكن إعادة المحاولة معها، بما في ذلك:
ClickHouseException- هذا استثناء عام يمكن أن يطرحه ClickHouse. ويُطرح عادةً عندما يكون الخادم مثقلًا، وتُعد رموز الخطأ التالية عابرة بشكل خاص:- 3 - UNEXPECTED_END_OF_FILE
- 107 - FILE_DOESNT_EXIST
- 159 - TIMEOUT_EXCEEDED
- 164 - READONLY
- 202 - TOO_MANY_SIMULTANEOUS_QUERIES
- 203 - NO_FREE_CONNECTION
- 209 - SOCKET_TIMEOUT
- 210 - NETWORK_ERROR
- 241 - MEMORY_LIMIT_EXCEEDED
- 242 - TABLE_IS_READ_ONLY
- 252 - TOO_MANY_PARTS
- 285 - TOO_FEW_LIVE_REPLICAS
- 319 - UNKNOWN_STATUS_OF_INSERT
- 425 - SYSTEM_ERROR
- 999 - KEEPER_EXCEPTION
SocketTimeoutException- يُطرح هذا عندما تنتهي مهلة المقبس.UnknownHostException- يُطرح هذا عندما يتعذر تحديد المضيف.IOException- يُطرح هذا عندما تكون هناك مشكلة في الشبكة.
"كل بياناتي فارغة/أصفار"
من المرجّح أن الحقول في بياناتك لا تتطابق مع الحقول في الجدول، وهذا شائع خصوصًا مع CDC (وتنسيق Debezium). أحد الحلول الشائعة هو إضافة تحويل flatten إلى إعدادات الموصل:
transforms=flatten
transforms.flatten.type=org.apache.kafka.connect.transforms.Flatten$Value
transforms.flatten.delimiter=_سيؤدي ذلك إلى تحويل بياناتك من JSON متداخل إلى JSON مُسطَّح (باستخدام _ كفاصل). وستتبع الحقول في الجدول بعد ذلك التنسيق "field1_field2_field3" (أي "before_id" و"after_id" وما إلى ذلك).
"أريد استخدام مفاتيح Kafka الخاصة بي في ClickHouse"
لا تُحفَظ مفاتيح Kafka في حقل القيمة بشكل افتراضي، لكن يمكنك استخدام التحويل KeyToValue لنقل المفتاح إلى حقل القيمة (ضمن حقل جديد باسم _key):
transforms=keyToValue
transforms.keyToValue.type=com.clickhouse.kafka.connect.transforms.KeyToValue
transforms.keyToValue.field=_key