Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

النسخ المتماثل + التوسيع

في هذا المثال، ستتعلّم كيفية إعداد عنقود ClickHouse بسيط يوفّر كلاً من التكرار والتوسعة. ويتكوّن من شاردين ونسختين متماثلتين، مع عنقود ClickHouse Keeper من 3 عقد لإدارة التناسق والحفاظ على النصاب داخل العنقود.

تظهر أدناه معمارية العنقود الذي ستقوم بإعداده:

مخطط المعمارية لشاردين ونسخة متماثلة واحدة

المتطلبات الأساسية

إعداد بنية الدليل وبيئة الاختبار

في هذا الدليل العملي، ستستخدم Docker compose لإعداد مجموعة ClickHouse. يمكن تعديل هذا الإعداد ليعمل على أجهزة محلية منفصلة، أو أجهزة افتراضية، أو نُسَخ سحابية كذلك.

نفّذ الأوامر التالية لإعداد بنية الدليل لهذا المثال:

mkdir cluster_2S_2R
cd cluster_2S_2R

# Create clickhouse-keeper directories
for i in {01..03}; do
  mkdir -p fs/volumes/clickhouse-keeper-${i}/etc/clickhouse-keeper
done

# Create clickhouse-server directories
for i in {01..04}; do
  mkdir -p fs/volumes/clickhouse-${i}/etc/clickhouse-server
done

أضف ملف docker-compose.yml التالي إلى دليل clickhouse-cluster:

docker-compose.ymlyaml
version: '3.8'
services:
  clickhouse-01:
    image: "clickhouse/clickhouse-server:latest"
    user: "101:101"
    container_name: clickhouse-01
    hostname: clickhouse-01
    volumes:
      - ${PWD}/fs/volumes/clickhouse-01/etc/clickhouse-server/config.d/config.xml:/etc/clickhouse-server/config.d/config.xml
      - ${PWD}/fs/volumes/clickhouse-01/etc/clickhouse-server/users.d/users.xml:/etc/clickhouse-server/users.d/users.xml
    ports:
      - "127.0.0.1:8123:8123"
      - "127.0.0.1:9000:9000"
    depends_on:
      - clickhouse-keeper-01
      - clickhouse-keeper-02
      - clickhouse-keeper-03
  clickhouse-02:
    image: "clickhouse/clickhouse-server:latest"
    user: "101:101"
    container_name: clickhouse-02
    hostname: clickhouse-02
    volumes:
      - ${PWD}/fs/volumes/clickhouse-02/etc/clickhouse-server/config.d/config.xml:/etc/clickhouse-server/config.d/config.xml
      - ${PWD}/fs/volumes/clickhouse-02/etc/clickhouse-server/users.d/users.xml:/etc/clickhouse-server/users.d/users.xml
    ports:
      - "127.0.0.1:8124:8123"
      - "127.0.0.1:9001:9000"
    depends_on:
      - clickhouse-keeper-01
      - clickhouse-keeper-02
      - clickhouse-keeper-03
  clickhouse-03:
    image: "clickhouse/clickhouse-server:latest"
    user: "101:101"
    container_name: clickhouse-03
    hostname: clickhouse-03
    volumes:
      - ${PWD}/fs/volumes/clickhouse-03/etc/clickhouse-server/config.d/config.xml:/etc/clickhouse-server/config.d/config.xml
      - ${PWD}/fs/volumes/clickhouse-03/etc/clickhouse-server/users.d/users.xml:/etc/clickhouse-server/users.d/users.xml
    ports:
      - "127.0.0.1:8125:8123"
      - "127.0.0.1:9002:9000"
    depends_on:
      - clickhouse-keeper-01
      - clickhouse-keeper-02
      - clickhouse-keeper-03
  clickhouse-04:
    image: "clickhouse/clickhouse-server:latest"
    user: "101:101"
    container_name: clickhouse-04
    hostname: clickhouse-04
    volumes:
      - ${PWD}/fs/volumes/clickhouse-04/etc/clickhouse-server/config.d/config.xml:/etc/clickhouse-server/config.d/config.xml
      - ${PWD}/fs/volumes/clickhouse-04/etc/clickhouse-server/users.d/users.xml:/etc/clickhouse-server/users.d/users.xml
    ports:
      - "127.0.0.1:8126:8123"
      - "127.0.0.1:9003:9000"
    depends_on:
      - clickhouse-keeper-01
      - clickhouse-keeper-02
      - clickhouse-keeper-03
  clickhouse-keeper-01:
    image: "clickhouse/clickhouse-keeper:latest-alpine"
    user: "101:101"
    container_name: clickhouse-keeper-01
    hostname: clickhouse-keeper-01
    volumes:
      - ${PWD}/fs/volumes/clickhouse-keeper-01/etc/clickhouse-keeper/keeper_config.xml:/etc/clickhouse-keeper/keeper_config.xml
    ports:
      - "127.0.0.1:9181:9181"
  clickhouse-keeper-02:
    image: "clickhouse/clickhouse-keeper:latest-alpine"
    user: "101:101"
    container_name: clickhouse-keeper-02
    hostname: clickhouse-keeper-02
    volumes:
      - ${PWD}/fs/volumes/clickhouse-keeper-02/etc/clickhouse-keeper/keeper_config.xml:/etc/clickhouse-keeper/keeper_config.xml
    ports:
      - "127.0.0.1:9182:9181"
  clickhouse-keeper-03:
    image: "clickhouse/clickhouse-keeper:latest-alpine"
    user: "101:101"
    container_name: clickhouse-keeper-03
    hostname: clickhouse-keeper-03
    volumes:
      - ${PWD}/fs/volumes/clickhouse-keeper-03/etc/clickhouse-keeper/keeper_config.xml:/etc/clickhouse-keeper/keeper_config.xml
    ports:
      - "127.0.0.1:9183:9181"

أنشئ المجلدات الفرعية والملفات التالية:

for i in {01..04}; do
  mkdir -p fs/volumes/clickhouse-${i}/etc/clickhouse-server/config.d
  mkdir -p fs/volumes/clickhouse-${i}/etc/clickhouse-server/users.d
  touch fs/volumes/clickhouse-${i}/etc/clickhouse-server/config.d/config.xml
  touch fs/volumes/clickhouse-${i}/etc/clickhouse-server/users.d/users.xml
done
  • يحتوي الدليل config.d على ملف إعدادات خادم ClickHouse ‏config.xml، حيث تُحدَّد الإعدادات المخصصة لكل عقدة ClickHouse. وتُدمَج هذه الإعدادات مع ملف إعدادات ClickHouse الافتراضي config.xml الذي يأتي مع كل عملية تثبيت لـ ClickHouse.
  • يحتوي الدليل users.d على ملف إعدادات المستخدم users.xml، حيث تُحدَّد الإعدادات المخصصة للمستخدمين. وتُدمَج هذه الإعدادات مع ملف إعدادات ClickHouse الافتراضي users.xml الذي يأتي مع كل عملية تثبيت لـ ClickHouse.

تهيئة عقد ClickHouse

إعداد الخادم

قم الآن بتعديل كل ملف تهيئة فارغ config.xml الموجود في fs/volumes/clickhouse-{}/etc/clickhouse-server/config.d. يجب تغيير الأسطر المميزة أدناه بحيث تكون خاصة بكل عقدة:

<clickhouse replace="true">
    <logger>
        <level>debug</level>
        <log>/var/log/clickhouse-server/clickhouse-server.log</log>
        <errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
        <size>1000M</size>
        <count>3</count>
    </logger>
    <display_name>cluster_2S_2R node 1</display_name>
    <listen_host>0.0.0.0</listen_host>
    <http_port>8123</http_port>
    <tcp_port>9000</tcp_port>
    <user_directories>
        <users_xml>
            <path>users.xml</path>
        </users_xml>
        <local_directory>
            <path>/var/lib/clickhouse/access/</path>
        </local_directory>
    </user_directories>
    <distributed_ddl>
        <path>/clickhouse/task_queue/ddl</path>
    </distributed_ddl>
    <remote_servers>
        <cluster_2S_2R>
            <shard>
                <internal_replication>true</internal_replication>
                <replica>
                    <host>clickhouse-01</host>
                    <port>9000</port>
                </replica>
                <replica>
                    <host>clickhouse-03</host>
                    <port>9000</port>
                </replica>
            </shard>
            <shard>
                <internal_replication>true</internal_replication>
                <replica>
                    <host>clickhouse-02</host>
                    <port>9000</port>
                </replica>
                <replica>
                    <host>clickhouse-04</host>
                    <port>9000</port>
                </replica>
            </shard>
        </cluster_2S_2R>
    </remote_servers>
    <zookeeper>
        <node>
            <host>clickhouse-keeper-01</host>
            <port>9181</port>
        </node>
        <node>
            <host>clickhouse-keeper-02</host>
            <port>9181</port>
        </node>
        <node>
            <host>clickhouse-keeper-03</host>
            <port>9181</port>
        </node>
    </zookeeper>
    <macros>
        <shard>01</shard>
        <replica>01</replica>
    </macros>
</clickhouse>
الدليل File
fs/volumes/clickhouse-01/etc/clickhouse-server/config.d config.xml
fs/volumes/clickhouse-02/etc/clickhouse-server/config.d config.xml
fs/volumes/clickhouse-03/etc/clickhouse-server/config.d config.xml
fs/volumes/clickhouse-04/etc/clickhouse-server/config.d config.xml

يُشرح كل قسم من أقسام ملف الإعداد أعلاه بمزيد من التفاصيل في ما يلي.

الشبكة والتسجيل

يُفعَّل الاتصال الخارجي عبر واجهة الشبكة من خلال تفعيل إعداد listen host. ويضمن ذلك أن يكون خادم ClickHouse قابلاً للوصول من قِبل المضيفات الأخرى:

<listen_host>0.0.0.0</listen_host>

تم ضبط منفذ واجهة برمجة تطبيقات HTTP على 8123:

<http_port>8123</http_port>

يُضبط منفذ TCP المستخدم للتواصل عبر البروتوكول الأصلي لـ ClickHouse بين clickhouse-client وأدوات ClickHouse الأصلية الأخرى، وبين clickhouse-server وخوادم clickhouse-server الأخرى على 9000:

<tcp_port>9000</tcp_port>

يُعرَّف إعداد التسجيل في كتلة <logger>. يوفر هذا المثال سجل تصحيح يُدوَّر عند 1000 ميغابايت ثلاث مرات:

<logger>
   <level>debug</level>
   <log>/var/log/clickhouse-server/clickhouse-server.log</log>
   <errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
   <size>1000M</size>
   <count>3</count>
</logger>

لمزيد من المعلومات حول تهيئة التسجيل، راجع التعليقات المضمّنة في ملف التهيئة الافتراضي لـ ClickHouse.

تهيئة الكلستر

يتم إعداد إعدادات الكلستر في مقطع <remote_servers>. هنا يُعرَّف اسم الكلستر cluster_2S_2R.

يُعرِّف الكتلة <cluster_2S_2R></cluster_2S_2R> تخطيط الكلستر باستخدام إعدادَي <shard></shard> و<replica></replica>، ويعمل كقالب لاستعلامات DDL الموزَّعة، وهي الاستعلامات التي تُنفَّذ عبر الكلستر بأكمله باستخدام جملة ON CLUSTER. تكون استعلامات DDL الموزَّعة مسموحاً بها افتراضياً، غير أنه يمكن تعطيلها عبر الإعداد allow_distributed_ddl_queries.

يُضبط internal_replication على true بحيث تُكتب البيانات إلى نسخة واحدة فقط من النسخ المتماثلة.

<remote_servers>
   <!-- cluster name (should not contain dots) -->
  <cluster_2S_2R>
      <!-- <allow_distributed_ddl_queries>false</allow_distributed_ddl_queries> -->
      <shard>
          <!-- Optional. Whether to write data to just one of the replicas. Default: false (write data to all replicas). -->
          <internal_replication>true</internal_replication>
          <replica>
              <host>clickhouse-01</host>
              <port>9000</port>
          </replica>
          <replica>
              <host>clickhouse-03</host>
              <port>9000</port>
          </replica>
      </shard>
      <shard>
          <internal_replication>true</internal_replication>
          <replica>
              <host>clickhouse-02</host>
              <port>9000</port>
          </replica>
          <replica>
              <host>clickhouse-04</host>
              <port>9000</port>
          </replica>
      </shard>
  </cluster_2S_2R>
</remote_servers>

يُحدِّد القسم <cluster_2S_2R></cluster_2S_2R> تخطيط الكلستر، ويعمل بوصفه template لاستعلامات DDL الموزَّعة، وهي الاستعلامات التي تُنفَّذ عبر الكلستر باستخدام جملة ON CLUSTER.

تهيئة Keeper

يُخبر القسم <ZooKeeper> ClickHouse بمكان تشغيل ClickHouse Keeper (أو ZooKeeper). نظرًا لاستخدامنا Keeper cluster، يجب تحديد كل <node> من عقد الـ cluster، مع الـ hostname ورقم المنفذ الخاص به باستخدام الوسمَين <host> و<port> على التوالي.

سيُشرح إعداد ClickHouse Keeper في الخطوة التالية من الدليل العملي.

<zookeeper>
    <node>
        <host>clickhouse-keeper-01</host>
        <port>9181</port>
    </node>
    <node>
        <host>clickhouse-keeper-02</host>
        <port>9181</port>
    </node>
    <node>
        <host>clickhouse-keeper-03</host>
        <port>9181</port>
    </node>
</zookeeper>

تهيئة الماكرو

بالإضافة إلى ذلك، يُستخدم قسم <macros> لتعريف استبدالات المعاملات للجداول المُكرَّرة. وتُدرج هذه الاستبدالات في system.macros، مما يتيح استخدام استبدالات مثل {shard} و{replica} في الاستعلامات.

<macros>
   <shard>01</shard>
   <replica>01</replica>
</macros>

تهيئة المستخدم

عدِّل الآن كل ملف تهيئة فارغ users.xml الموجود في fs/volumes/clickhouse-{}/etc/clickhouse-server/users.d بإضافة ما يلي:

/users.d/users.xmlxml
<?xml version="1.0"?>
<clickhouse replace="true">
    <profiles>
        <default>
            <max_memory_usage>10000000000</max_memory_usage>
            <use_uncompressed_cache>0</use_uncompressed_cache>
            <load_balancing>in_order</load_balancing>
            <log_queries>1</log_queries>
        </default>
    </profiles>
    <users>
        <default>
            <access_management>1</access_management>
            <profile>default</profile>
            <networks>
                <ip>::/0</ip>
            </networks>
            <quota>default</quota>
            <access_management>1</access_management>
            <named_collection_control>1</named_collection_control>
            <show_named_collections>1</show_named_collections>
            <show_named_collections_secrets>1</show_named_collections_secrets>
        </default>
    </users>
    <quotas>
        <default>
            <interval>
                <duration>3600</duration>
                <queries>0</queries>
                <errors>0</errors>
                <result_rows>0</result_rows>
                <read_rows>0</read_rows>
                <execution_time>0</execution_time>
            </interval>
        </default>
    </quotas>
</clickhouse>

في هذا المثال، تم تكوين المستخدم default بدون كلمة مرور لتبسيط الإعداد. في التطبيق الفعلي، لا يُنصح بهذا الأسلوب.

إعداد ClickHouse Keeper

بعد ذلك، ستُعِد ClickHouse Keeper، والذي يُستخدم للتنسيق.

إعداد Keeper

لكي يعمل النسخ المتماثل، يجب إعداد عنقود ClickHouse Keeper وتهيئته. يوفّر ClickHouse Keeper نظام التنسيق لنسخ البيانات المتماثل، إذ يعمل كبديل مباشر لـ ZooKeeper، الذي يمكن استخدامه أيضًا. ومع ذلك، يُوصى باستخدام ClickHouse Keeper لأنه يوفّر ضمانات أفضل وموثوقية أعلى ويستخدم موارد أقل من ZooKeeper. ولتحقيق التوافر العالي والحفاظ على quorum، يُوصى بتشغيل ثلاث عقد ClickHouse Keeper على الأقل.

أنشئ ملفات keeper_config.xml لكل عقدة ClickHouse Keeper باستخدام الأمر التالي من جذر مجلد المثال:

for i in {01..03}; do
  touch fs/volumes/clickhouse-keeper-${i}/etc/clickhouse-keeper/keeper_config.xml
done

عدِّل ملفات التكوين الفارغة التي أُنشئت في دليل كل عقدة fs/volumes/clickhouse-keeper-{}/etc/clickhouse-keeper. يجب تعديل الأسطر المظللة أدناه بحيث تكون خاصة بكل عقدة:

/clickhouse-keeper/keeper_config.xmlxml
<clickhouse replace="true">
    <logger>
        <level>information</level>
        <log>/var/log/clickhouse-keeper/clickhouse-keeper.log</log>
        <errorlog>/var/log/clickhouse-keeper/clickhouse-keeper.err.log</errorlog>
        <size>1000M</size>
        <count>3</count>
    </logger>
    <listen_host>0.0.0.0</listen_host>
    <keeper_server>
        <tcp_port>9181</tcp_port>
        <server_id>1</server_id>
        <log_storage_path>/var/lib/clickhouse/coordination/log</log_storage_path>
        <snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path>
        <coordination_settings>
            <operation_timeout_ms>10000</operation_timeout_ms>
            <session_timeout_ms>30000</session_timeout_ms>
            <raft_logs_level>information</raft_logs_level>
        </coordination_settings>
        <raft_configuration>
            <server>
                <id>1</id>
                <hostname>clickhouse-keeper-01</hostname>
                <port>9234</port>
            </server>
            <server>
                <id>2</id>
                <hostname>clickhouse-keeper-02</hostname>
                <port>9234</port>
            </server>
            <server>
                <id>3</id>
                <hostname>clickhouse-keeper-03</hostname>
                <port>9234</port>
            </server>
        </raft_configuration>
    </keeper_server>
</clickhouse>
الدليل الملف
fs/volumes/clickhouse-keeper-01/etc/clickhouse-keeper keeper_config.xml
fs/volumes/clickhouse-keeper-02/etc/clickhouse-keeper keeper_config.xml
fs/volumes/clickhouse-keeper-03/etc/clickhouse-keeper keeper_config.xml

سيحتوي كل ملف تهيئة على التكوين الفريد التالي (كما هو موضح أدناه). يجب أن يكون server_id المستخدم فريدًا لتلك العقدة المحددة من ClickHouse Keeper ضمن العنقود، وأن يطابق <id> الخاص بالخادم المعرّف في قسم <raft_configuration>. يمثل tcp_port المنفذ الذي يستخدمه عملاء ClickHouse Keeper.

<tcp_port>9181</tcp_port>
<server_id>{id}</server_id>

يُستخدم القسم التالي لتكوين الخوادم المشاركة في النصاب ضمن خوارزمية إجماع Raft:

<raft_configuration>
    <server>
        <id>1</id>
        <hostname>clickhouse-keeper-01</hostname>
        <!-- TCP port used for communication between ClickHouse Keeper nodes -->
        <port>9234</port>
    </server>
    <server>
        <id>2</id>
        <hostname>clickhouse-keeper-02</hostname>
        <port>9234</port>
    </server>
    <server>
        <id>3</id>
        <hostname>clickhouse-keeper-03</hostname>
        <port>9234</port>
    </server>
</raft_configuration>

اختبر الإعداد

تأكد من أن Docker قيد التشغيل على جهازك. ابدأ الـ cluster باستخدام الأمر docker-compose up من الدليل الجذر cluster_2S_2R:

docker-compose up -d

يجب أن ترى Docker يبدأ بسحب صور ClickHouse وKeeper، ثم يشغّل الحاويات:

[+] Running 8/8
 Network   cluster_2s_2r_default     Created
 Container clickhouse-keeper-03      Started
 Container clickhouse-keeper-02      Started
 Container clickhouse-keeper-01      Started
 Container clickhouse-01             Started
 Container clickhouse-02             Started
 Container clickhouse-04             Started
 Container clickhouse-03             Started

للتحقق من أن الـcluster يعمل، اتصل بأي عقدة منه وشغّل الاستعلام التالي. يظهر أدناه أمر الاتصال بالعقدة الأولى:

# Connect to any node
docker exec -it clickhouse-01 clickhouse-client

إذا نجحت العملية، فسيظهر لك موجّه ClickHouse client:

cluster_2S_2R node 1 :)

نفّذ الاستعلام التالي للتحقق من طوبولوجيات العناقيد المعرّفة والمضيفات التابعة لها:

Querysql
SELECT 
    cluster,
    shard_num,
    replica_num,
    host_name,
    port
FROM system.clusters;
Responseresponse
   ┌─cluster───────┬─shard_num─┬─replica_num─┬─host_name─────┬─port─┐
1. │ cluster_2S_2R │         1 │           1 │ clickhouse-01 │ 9000 │
2. │ cluster_2S_2R │         1 │           2 │ clickhouse-03 │ 9000 │
3. │ cluster_2S_2R │         2 │           1 │ clickhouse-02 │ 9000 │
4. │ cluster_2S_2R │         2 │           2 │ clickhouse-04 │ 9000 │
5. │ default       │         1 │           1 │ localhost     │ 9000 │
   └───────────────┴───────────┴─────────────┴───────────────┴──────┘

نفّذ الاستعلام التالي للتحقق من حالة عنقود ClickHouse Keeper:

Querysql
SELECT *
FROM system.zookeeper
WHERE path IN ('/', '/clickhouse')
Responseresponse
   ┌─name───────┬─value─┬─path────────┐
1. │ task_queue │       │ /clickhouse │
2. │ sessions   │       │ /clickhouse │
3. │ keeper     │       │ /           │
4. │ clickhouse │       │ /           │
   └────────────┴───────┴─────────────┘

يُستخدم الأمر mntr أيضًا على نطاق واسع للتحقق من أن ClickHouse Keeper قيد التشغيل، وللحصول على معلومات عن حالة العلاقة بين عقد Keeper الثلاث. في الإعداد المستخدم في هذا المثال، هناك ثلاث عقد تعمل معًا. ستنتخب هذه العقد قائدًا، وستكون العقد المتبقية عقدًا تابعة.

يوفّر الأمر mntr معلومات متعلقة بالأداء، ويُبيّن أيضًا ما إذا كانت عقدة معيّنة تابعة أم قائدًا.

شغّل الأمر أدناه من سطر الأوامر على clickhouse-keeper-01 وclickhouse-keeper-02 و clickhouse-keeper-03 للتحقق من حالة كل عقدة Keeper. الأمر الخاص بـ clickhouse-keeper-01 موضح أدناه:

docker exec -it clickhouse-keeper-01  /bin/sh -c 'echo mntr | nc 127.0.0.1 9181'

تعرض الاستجابة أدناه مثالًا على استجابة من عقدة follower:

Responseresponse
zk_version      v23.3.1.2823-testing-46e85357ce2da2a99f56ee83a079e892d7ec3726
zk_avg_latency  0
zk_max_latency  0
zk_min_latency  0
zk_packets_received     0
zk_packets_sent 0
zk_num_alive_connections        0
zk_outstanding_requests 0
zk_server_state follower
zk_znode_count  6
zk_watch_count  0
zk_ephemerals_count     0
zk_approximate_data_size        1271
zk_key_arena_size       4096
zk_latest_snapshot_size 0
zk_open_file_descriptor_count   46
zk_max_file_descriptor_count    18446744073709551615

يوضح الرد أدناه مثالًا لرد صادر من العقدة القائدة:

Responseresponse
zk_version      v23.3.1.2823-testing-46e85357ce2da2a99f56ee83a079e892d7ec3726
zk_avg_latency  0
zk_max_latency  0
zk_min_latency  0
zk_packets_received     0
zk_packets_sent 0
zk_num_alive_connections        0
zk_outstanding_requests 0
zk_server_state leader
zk_znode_count  6
zk_watch_count  0
zk_ephemerals_count     0
zk_approximate_data_size        1271
zk_key_arena_size       4096
zk_latest_snapshot_size 0
zk_open_file_descriptor_count   48
zk_max_file_descriptor_count    18446744073709551615
zk_followers    2
zk_synced_followers     2

بهذا، تكون قد أعددت بنجاح عنقود ClickHouse يضم شاردين ونسختين متماثلتين. في الخطوة التالية، ستنشئ جدولًا على العنقود.

إنشاء قاعدة بيانات

الآن، بعد أن تحققت من أن العنقود مُعَدّ بشكل صحيح ويعمل، ستعيد إنشاء الجدول نفسه المستخدم في الدليل العملي لمجموعة البيانات النموذجية أسعار العقارات في المملكة المتحدة. ويحتوي على نحو 30 مليون صفّ من أسعار العقارات المدفوعة للعقارات في إنجلترا وويلز منذ عام 1995.

اتصل بعميل كل مضيف بتشغيل كل واحد من الأوامر التالية من تبويبات طرفية أو نوافذ منفصلة:

docker exec -it clickhouse-01 clickhouse-client
docker exec -it clickhouse-02 clickhouse-client
docker exec -it clickhouse-03 clickhouse-client
docker exec -it clickhouse-04 clickhouse-client

يمكنك تشغيل الاستعلام أدناه من clickhouse-client على كل مضيف للتأكد من أنه لم يتم إنشاء أي قواعد بيانات بعد، باستثناء القواعد الافتراضية:

Querysql
SHOW DATABASES;
Responseresponse
   ┌─name───────────────┐
1. │ INFORMATION_SCHEMA │
2. │ default            │
3. │ information_schema │
4. │ system             │
   └────────────────────┘

من العميل clickhouse-01، شغّل استعلام DDL موزّع التالي باستخدام بند ON CLUSTER لإنشاء قاعدة بيانات جديدة باسم uk:

CREATE DATABASE IF NOT EXISTS uk 
ON CLUSTER cluster_2S_2R;

يمكنك مرة أخرى تشغيل الاستعلام نفسه كما في السابق من عميل كل مضيف للتأكد من أن قاعدة البيانات قد أُنشئت على مستوى العنقود رغم تشغيل الاستعلام من clickhouse-01 فقط:

SHOW DATABASES;
   ┌─name───────────────┐
1. │ INFORMATION_SCHEMA │
2. │ default            │
3. │ information_schema │
4. │ system             │
5. │ uk                 │
   └────────────────────┘

أنشئ جدولًا على العنقود

الآن بعد إنشاء قاعدة البيانات، أنشئ جدولًا مع النسخ المتماثل.

شغّل الاستعلام التالي من أي عميل على أي مضيف:

CREATE TABLE IF NOT EXISTS uk.uk_price_paid_local
ON CLUSTER cluster_2S_2R
(
    price UInt32,
    date Date,
    postcode1 LowCardinality(String),
    postcode2 LowCardinality(String),
    type Enum8('terraced' = 1, 'semi-detached' = 2, 'detached' = 3, 'flat' = 4, 'other' = 0),
    is_new UInt8,
    duration Enum8('freehold' = 1, 'leasehold' = 2, 'unknown' = 0),
    addr1 String,
    addr2 String,
    street LowCardinality(String),
    locality LowCardinality(String),
    town LowCardinality(String),
    district LowCardinality(String),
    county LowCardinality(String)
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{database}/{table}/{shard}', '{replica}')
ORDER BY (postcode1, postcode2, addr1, addr2);

لاحظ أنه مطابق للاستعلام المستخدم في دليل عملي لمجموعة البيانات النموذجية UK property prices الأصلي ضمن عبارة CREATE، باستثناء عبارة ON CLUSTER واستخدام المحرك ReplicatedMergeTree.

صُمِّمت عبارة ON CLUSTER للتنفيذ الموزع لاستعلامات DDL (لغة تعريف البيانات) مثل CREATE وDROP وALTER وRENAME، بما يضمن تطبيق تغييرات المخطط هذه على جميع العقد في المجموعة.

يعمل المحرك ReplicatedMergeTree تمامًا مثل محرك الجداول العادي MergeTree، لكنه ينسخ البيانات أيضًا. ويتطلب تحديد مَعلمَين:

  • zoo_path: مسار Keeper/ZooKeeper إلى البيانات الوصفية للجدول.
  • replica_name: اسم النسخة المتماثلة للجدول.

يمكن ضبط المَعلَم zoo_path على أي قيمة تختارها، مع أنه يُوصى باتباع الاصطلاح القائم على استخدام البادئة

/clickhouse/tables/{shard}/{database}/{table}

حيث:

  • سيتم استبدال {database} و{table} تلقائيًا.
  • إن {shard} و{replica} عبارتان من نوع الماكرو جرى تعريفهما سابقًا في ملف config.xml لكل عقدة من عقد ClickHouse.

يمكنك تشغيل الاستعلام أدناه من العميل على كل مضيف للتأكد من أن الجدول قد أُنشئ عبر العنقود:

Querysql
SHOW TABLES IN uk;
Responseresponse
   ┌─name────────────────┐
1. │ uk_price_paid_local │
   └─────────────────────┘

إدراج البيانات في جدول موزّع

لإدراج البيانات في الجدول، لا يمكن استخدام ON CLUSTER لأنه لا ينطبق على استعلامات DML (لغة معالجة البيانات) مثل INSERT وUPDATE وDELETE. ولإدراج البيانات، يجب استخدام محرّك الجدول Distributed. وكما تعلّمت في الدليل الخاص بإعداد عنقود يضم جزأين ونسخة متماثلة واحدة، فإن الجداول الموزّعة هي جداول يمكنها الوصول إلى الأجزاء الموجودة على مضيفين مختلفين، وتُعرَّف باستخدام محرّك الجدول Distributed. ويعمل الجدول الموزّع بوصفه واجهة موحّدة عبر جميع الأجزاء في العنقود.

من أي عميل على أحد المضيفين، شغّل الاستعلام التالي لإنشاء جدول موزّع باستخدام الجدول المتماثل الحالي الذي أنشأناه في الخطوة السابقة:

CREATE TABLE IF NOT EXISTS uk.uk_price_paid_distributed
ON CLUSTER cluster_2S_2R
ENGINE = Distributed('cluster_2S_2R', 'uk', 'uk_price_paid_local', rand());

على كل مضيف، سترى الآن الجداول التالية في قاعدة البيانات uk:

   ┌─name──────────────────────┐
1. │ uk_price_paid_distributed │
2. │ uk_price_paid_local       │
   └───────────────────────────┘

يمكن إدراج البيانات في جدول uk_price_paid_distributed من أيٍّ من العملاء على المضيفات باستخدام الاستعلام التالي:

INSERT INTO uk.uk_price_paid_distributed
SELECT
    toUInt32(price_string) AS price,
    parseDateTimeBestEffortUS(time) AS date,
    splitByChar(' ', postcode)[1] AS postcode1,
    splitByChar(' ', postcode)[2] AS postcode2,
    transform(a, ['T', 'S', 'D', 'F', 'O'], ['terraced', 'semi-detached', 'detached', 'flat', 'other']) AS type,
    b = 'Y' AS is_new,
    transform(c, ['F', 'L', 'U'], ['freehold', 'leasehold', 'unknown']) AS duration,
    addr1,
    addr2,
    street,
    locality,
    town,
    district,
    county
FROM url(
    'http://prod1.publicdata.landregistry.gov.uk.s3-website-eu-west-1.amazonaws.com/pp-complete.csv',
    'CSV',
    'uuid_string String,
    price_string String,
    time String,
    postcode String,
    a String,
    b String,
    c String,
    addr1 String,
    addr2 String,
    street String,
    locality String,
    town String,
    district String,
    county String,
    d String,
    e String'
) SETTINGS max_http_get_redirects=10;

شغّل الاستعلام التالي للتأكد من أن البيانات المُدخلة قد وُزِّعت بالتساوي عبر عُقد العنقود:

SELECT count(*)
FROM uk.uk_price_paid_distributed;

SELECT count(*) FROM uk.uk_price_paid_local;
   ┌──count()─┐
1. │ 30212555 │ -- 30.21 million
   └──────────┘

   ┌──count()─┐
1. │ 15105983 │ -- 15.11 million
   └──────────┘

الخلاصة

تتمثل ميزة بنية العُنقود هذه، التي تضم شاردين ونسختين متماثلتين، في أنها توفّر كلاً من قابلية التوسع وتحمل الأعطال. تُوزَّع البيانات عبر مضيفين منفصلين، مما يقلّل متطلبات التخزين وعمليات الإدخال/الإخراج لكل عقدة، بينما تُعالَج الاستعلامات بالتوازي عبر كلا الشاردين لتحسين الأداء وكفاءة استخدام الذاكرة. والأهم من ذلك أن العُنقود يستطيع تحمّل فقدان عقدة واحدة ومواصلة خدمة الاستعلامات دون انقطاع، إذ تتوفر لكل شارد نسخة متماثلة احتياطية على عقدة أخرى.

أما العيب الرئيسي في بنية العُنقود هذه فهو زيادة العبء التخزيني—إذ تتطلب سعة تخزين مضاعفة مقارنة بإعداد لا يحتوي على نسخ متماثلة، لأن كل شارد يكون مكرراً. بالإضافة إلى ذلك، ورغم أن العُنقود يمكنه الصمود أمام تعطل عقدة واحدة، فإن فقدان عقدتين في الوقت نفسه قد يجعل العُنقود غير قابل للتشغيل، وذلك بحسب العقد التي تتعطل وكيفية توزيع الشاردات. تحقق هذه البنية توازناً بين الإتاحة والتكلفة، مما يجعلها مناسبة لبيئات production التي تتطلب مستوى معيناً من تحمل الأعطال من دون كلفة عوامل نسخ متماثل أعلى.

للتعرّف على كيفية معالجة ClickHouse Cloud للاستعلامات، بما يوفّر كلاً من قابلية التوسع وتحمل الأعطال، راجع قسم "Parallel Replicas".

Navigation