Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

النسخ المتماثل للبيانات

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

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

مخطط معمارية لجزء بيانات واحد ونسختين متماثلتين باستخدام ReplicatedMergeTree

المتطلبات المسبقة

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

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

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

mkdir cluster_1S_2R
cd cluster_1S_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..02}; do
  mkdir -p fs/volumes/clickhouse-${i}/etc/clickhouse-server
done

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

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-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..02}; 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_1S_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_1S_2R>
            <shard>
                <internal_replication>true</internal_replication>
                <replica>
                    <host>clickhouse-01</host>
                    <port>9000</port>
                </replica>
                <replica>
                    <host>clickhouse-02</host>
                    <port>9000</port>
                </replica>
            </shard>
        </cluster_1S_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>
        <cluster>cluster_1S_2R</cluster>
    </macros>
</clickhouse>
الدليل الملف
fs/volumes/clickhouse-01/etc/clickhouse-server/config.d config.xml
fs/volumes/clickhouse-02/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>. توفر لك هذه التهيئة النموذجية سجل تصحيح يُدوَّر عند 1000M ثلاث مرات:

<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_1S_2R.

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

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

<remote_servers>
    <!-- cluster name (should not contain dots) -->
    <cluster_1S_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-02</host>
                <port>9000</port>
            </replica>
        </shard>
    </cluster_1S_2R>
</remote_servers>

لكل خادم، تُحدَّد المعلمات التالية:

Parameter Description Default Value
host عنوان الخادم البعيد. يمكنك استخدام اسم النطاق أو عنوان IPv4 أو IPv6. إذا حددت اسم النطاق، فسيُجري الخادم طلب DNS عند بدء التشغيل، وتُحفَظ النتيجة طوال مدة تشغيل الخادم. إذا فشل طلب DNS، فلن يبدأ الخادم. وإذا غيّرت سجل DNS، فستحتاج إلى إعادة تشغيل الخادم. -
port منفذ TCP لنشاط المراسلة (tcp_port في الإعدادات، ويُضبط عادةً على 9000). لا تخلطه مع http_port. -

تهيئة 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>
    <cluster>cluster_1S_2R</cluster>
</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>
المجلد File
fs/volumes/clickhouse-01/etc/clickhouse-server/users.d users.xml
fs/volumes/clickhouse-02/etc/clickhouse-server/users.d users.xml

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

إعداد 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 يعمل على جهازك. ابدأ العنقود باستخدام الأمر docker-compose up من الدليل الجذر cluster_1S_2R:

docker-compose up -d

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

[+] Running 6/6
 Network cluster_1s_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

للتحقق من أن التجمّع يعمل، اتصل بـ clickhouse-01 أو clickhouse-02 ونفّذ الاستعلام التالي. وفيما يلي أمر الاتصال بالعقدة الأولى:

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

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

cluster_1S_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_1S_2R │         1 │           1 │ clickhouse-01 │ 9000 │
2. │ cluster_1S_2R │         1 │           2 │ clickhouse-02 │ 9000 │
3. │ default       │         1 │           1 │ localhost     │ 9000 │
   └───────────────┴───────────┴─────────────┴───────────────┴──────┘

شغّل الاستعلام التالي للتحقق من حالة تجمّع ClickHouse Keeper:

Querysql
SELECT *
FROM system.zookeeper
WHERE path IN ('/', '/clickhouse')
Responseresponse
   ┌─name───────┬─value─┬─path────────┐
1. │ sessions   │       │ /clickhouse │
2. │ task_queue │       │ /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 بشظية واحدة ونسختين متماثلتين. في الخطوة التالية، ستنشئ جدولًا في العنقود.

أنشئ قاعدة بيانات

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

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

docker exec -it clickhouse-01 clickhouse-client
docker exec -it clickhouse-02 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_1S_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_1S_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
ORDER BY (postcode1, postcode2, addr1, addr2);

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

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

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

يمكنك تشغيل الاستعلام أدناه من عميل clickhouse-01 أو clickhouse-02 للتأكد من أن الجدول قد أُنشئ على مستوى العنقود:

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

إدراج البيانات

نظرًا لأن مجموعة البيانات كبيرة وتستغرق بضع دقائق لاستيعابها بالكامل، سنبدأ بإدراج جزء صغير منها فحسب.

أدرج مجموعة فرعية أصغر من البيانات باستخدام الاستعلام أدناه من clickhouse-01:

INSERT INTO uk.uk_price_paid_local
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'
) LIMIT 10000
SETTINGS max_http_get_redirects=10;

لاحظ أن البيانات مُنسوخة بالكامل على كل عقدة:

-- clickhouse-01
SELECT count(*)
FROM uk.uk_price_paid_local

--   ┌─count()─┐
-- 1.│   10000 │
--   └─────────┘

-- clickhouse-02
SELECT count(*)
FROM uk.uk_price_paid_local

--   ┌─count()─┐
-- 1.│   10000 │
--   └─────────┘

لتوضيح ما يحدث عند تعطّل أحد المضيفين، أنشئ قاعدة بيانات اختبارية بسيطة وجدول اختبار من أيٍّ من المضيفين:

CREATE DATABASE IF NOT EXISTS test ON CLUSTER cluster_1S_2R;
CREATE TABLE test.test_table ON CLUSTER cluster_1S_2R
(
    `id` UInt64,
    `name` String
)
ENGINE = ReplicatedMergeTree
ORDER BY id;

كما هو الحال مع جدول uk_price_paid، يمكننا إدراج البيانات من أيٍّ من المضيفَين:

INSERT INTO test.test_table (id, name) VALUES (1, 'Clicky McClickface');

لكن ماذا سيحدث إذا تعطّل أحد المضيفين؟ لمحاكاة ذلك، أوقف clickhouse-01 بتنفيذ الأمر التالي:

docker stop clickhouse-01

تحقق من أن المضيف متوقف عن طريق تشغيل:

docker-compose ps
Responseresponse
NAME                   IMAGE                                        COMMAND            SERVICE                CREATED          STATUS          PORTS
clickhouse-02          clickhouse/clickhouse-server:latest          "/entrypoint.sh"   clickhouse-02          X minutes ago    Up X minutes    127.0.0.1:8124->8123/tcp, 127.0.0.1:9001->9000/tcp
clickhouse-keeper-01   clickhouse/clickhouse-keeper:latest-alpine   "/entrypoint.sh"   clickhouse-keeper-01   X minutes ago    Up X minutes    127.0.0.1:9181->9181/tcp
clickhouse-keeper-02   clickhouse/clickhouse-keeper:latest-alpine   "/entrypoint.sh"   clickhouse-keeper-02   X minutes ago    Up X minutes    127.0.0.1:9182->9181/tcp
clickhouse-keeper-03   clickhouse/clickhouse-keeper:latest-alpine   "/entrypoint.sh"   clickhouse-keeper-03   X minutes ago    Up X minutes    127.0.0.1:9183->9181/tcp

بعد إيقاف clickhouse-01، أدرج صفًا آخر من البيانات في جدول الاختبار واستعلم عن الجدول:

INSERT INTO test.test_table (id, name) VALUES (2, 'Alexey Milovidov');
SELECT * FROM test.test_table;
Responseresponse
   ┌─id─┬─name───────────────┐
1. │  1 │ Clicky McClickface │
2. │  2 │ Alexey Milovidov   │
   └────┴────────────────────┘

أعد تشغيل clickhouse-01 الآن باستخدام الأمر التالي (يمكنك تشغيل docker-compose ps مجدداً للتحقق من ذلك):

docker start clickhouse-01

استعلم عن جدول الاختبار مجدداً من clickhouse-01 بعد تشغيل docker exec -it clickhouse-01 clickhouse-client:

Querysql
SELECT * FROM test.test_table
Responseresponse
   ┌─id─┬─name───────────────┐
1. │  1 │ Clicky McClickface │
2. │  2 │ Alexey Milovidov   │
   └────┴────────────────────┘

إذا كنت في هذه المرحلة ترغب في استيراد مجموعة بيانات أسعار العقارات في المملكة المتحدة بالكامل للتجربة والاستكشاف، يمكنك تشغيل الاستعلامات التالية:

TRUNCATE TABLE uk.uk_price_paid_local ON CLUSTER cluster_1S_2R;
INSERT INTO uk.uk_price_paid_local
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;

استعلم عن الجدول من clickhouse-02 أو clickhouse-01:

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

الخلاصة

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

عندما يتوقف أحد الخادمين عن العمل، تظل النسخة المتماثلة المتبقية قادرة على:

  • معالجة استعلامات القراءة دون انقطاع
  • قبول عمليات كتابة جديدة (بحسب إعدادات الاتساق لديك)
  • الحفاظ على إتاحة الخدمة للتطبيقات

عندما يعود الخادم المتعطل إلى العمل، يصبح قادرًا على:

  • مزامنة البيانات المفقودة تلقائيًا من النسخة المتماثلة السليمة
  • استئناف التشغيل الطبيعي دون تدخل يدوي
  • استعادة التكرار الكامل بسرعة

في المثال التالي، سنستعرض كيفية إعداد عنقود يضم شاردتين لكن بنسخة متماثلة واحدة فقط.

Navigation