> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# التوسع

> صفحة تصف مثالًا على معمارية مصممة لتوفير قابلية التوسع

export const Image = ({img, alt, size = "lg"}) => {
  const normalizedSize = ["sm", "md", "lg"].includes(size) ? size : "lg";
  return <div className={`ch-image-${normalizedSize}`}>
      <Frame>
        <img src={img} alt={alt} />
      </Frame>
    </div>;
};

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

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

<Image img="https://mintcdn.com/private-7c7dfe99/NvnCM4vX9aZ07JxK/images/deployment-guides/replication-sharding-examples/sharding.webp?fit=max&auto=format&n=NvnCM4vX9aZ07JxK&q=85&s=bb9b9d42024b0aed234f3cc36f854628" size="md" alt="مخطط معمارية لشاردين ونسخة متماثلة واحدة" width="1200" height="800" data-path="images/deployment-guides/replication-sharding-examples/sharding.webp" />

<Note>
  على الرغم من إمكانية تشغيل ClickHouse Server وClickHouse Keeper معًا على الخادم نفسه،
  فإننا نوصي بشدة باستخدام مضيفات *مخصصة* لـ ClickHouse Keeper في بيئات production،
  وهذا هو النهج الذي سنوضحه في هذا المثال.

  يمكن أن تكون خوادم Keeper أصغر حجمًا، وعادةً ما تكون 4GB RAM كافية لكل خادم Keeper
  إلى أن تكبر ClickHouse Servers.
</Note>

<div id="pre-requisites">
  ## المتطلبات الأساسية
</div>

* سبق أن قمتَ بإعداد [خادم ClickHouse محلي](/docs/ar/get-started/setup/install)
* أنت على دراية بمفاهيم الإعداد الأساسية في ClickHouse، مثل [ملفات الإعداد](/docs/ar/concepts/features/configuration/server-config/configuration-files)
* Docker مُثبَّت على جهازك

<Steps>
  <Step title="إعداد بنية الدليل وبيئة الاختبار" id="set-up">
    <Tip>
      **ملفات المثال**

      توضح لك الخطوات التالية كيفية إعداد العنقود من
      الصفر. إذا كنت تفضل تخطي هذه الخطوات والانتقال مباشرةً إلى تشغيل
      العنقود، فيمكنك الحصول على ملفات
      المثال من مستودع الأمثلة [مجلد 'docker-compose-recipes'](https://github.com/ClickHouse/examples/tree/main/docker-compose-recipes/recipes).
    </Tip>

    في هذا الدليل العملي، ستستخدم [Docker compose](https://docs.docker.com/compose/) لإعداد مجموعة ClickHouse. يمكن تعديل هذا الإعداد ليعمل على أجهزة محلية منفصلة، أو أجهزة افتراضية، أو نسخ سحابية كذلك.

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

    ```bash theme={null}
    mkdir cluster_2S_1R
    cd cluster_2S_1R

    # 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_2S_1R`:

    ```yaml title="docker-compose.yml" theme={null}
    version: '3.8'
    services:
      clickhouse-01:
        image: "clickhouse/clickhouse-server:latest"
        user: "101:101"
        container_name: clickhouse-01
        hostname: clickhouse-01
        networks:
          cluster_2S_1R:
            ipv4_address: 192.168.7.1
        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
        networks:
          cluster_2S_1R:
            ipv4_address: 192.168.7.2
        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
        networks:
          cluster_2S_1R:
            ipv4_address: 192.168.7.5
        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
        networks:
          cluster_2S_1R:
            ipv4_address: 192.168.7.6
        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
        networks:
          cluster_2S_1R:
            ipv4_address: 192.168.7.7
        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"
    networks:
      cluster_2S_1R:
        driver: bridge
        ipam:
          config:
            - subnet: 192.168.7.0/24
              gateway: 192.168.7.254
    ```

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

    ```bash theme={null}
    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.

    <Tip>
      **أدلة الإعدادات المخصصة**

      من أفضل الممارسات استخدام الدليلين `config.d` و`users.d` عند
      كتابة إعداداتك الخاصة، بدلًا من تعديل الإعدادات الافتراضية مباشرةً
      في `/etc/clickhouse-server/config.xml` و`etc/clickhouse-server/users.xml`.

      السطر

      ```xml theme={null}
      <clickhouse replace="true">
      ```

      يضمن أن أقسام الإعدادات المحددة في الدليلين `config.d` و`users.d`
      تحلّ محل أقسام الإعدادات الافتراضية المحددة في الملفين الافتراضيين
      `config.xml` و`users.xml`.
    </Tip>
  </Step>

  <Step title="تهيئة عقد ClickHouse" id="configure-clickhouse-servers">
    ### إعداد الخادم

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

    ```xml highlight={9,54-57} theme={null}
    <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_1R 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_1R>
                <shard>
                    <replica>
                        <host>clickhouse-01</host>
                        <port>9000</port>
                    </replica>
                </shard>
                <shard>
                    <replica>
                        <host>clickhouse-02</host>
                        <port>9000</port>
                    </replica>
                </shard>
            </cluster_2S_1R>
        </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`](https://github.com/ClickHouse/examples/blob/main/docker-compose-recipes/recipes/cluster_2S_1R/fs/volumes/clickhouse-01/etc/clickhouse-server/config.d/config.xml) |
    | `fs/volumes/clickhouse-02/etc/clickhouse-server/config.d` | [`config.xml`](https://github.com/ClickHouse/examples/blob/main/docker-compose-recipes/recipes/cluster_2S_1R/fs/volumes/clickhouse-02/etc/clickhouse-server/config.d/config.xml) |

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

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

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

    ```xml theme={null}
    <listen_host>0.0.0.0</listen_host>
    ```

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

    ```xml theme={null}
    <http_port>8123</http_port>
    ```

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

    ```xml theme={null}
    <tcp_port>9000</tcp_port>
    ```

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

    ```xml theme={null}
    <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>
    ```

    لمزيد من المعلومات حول تهيئة التسجيل، راجع التعليقات المضمّنة في
    [ملف التهيئة](https://github.com/ClickHouse/ClickHouse/blob/master/programs/server/config.xml) الافتراضي لـ ClickHouse.

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

    يتم ضبط إعداد الكتلة في القسم `<remote_servers>`.
    هنا يُحدَّد اسم الكتلة `cluster_2S_1R`.

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

    يُترك `internal_replication` مضبوطاً على false بشكل افتراضي نظراً لوجود نسخة واحدة فقط لكل جزء.

    ```xml theme={null}
    <remote_servers>
        <cluster_2S_1R>
            <shard>
                <replica>
                    <host>clickhouse-01</host>
                    <port>9000</port>
                </replica>
            </shard>
            <shard>
                <replica>
                    <host>clickhouse-02</host>
                    <port>9000</port>
                </replica>
            </shard>
        </cluster_2S_1R>
    </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 في الخطوة التالية من الدليل العملي.

    ```xml theme={null}
    <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>
    ```

    <Note>
      على الرغم من أنه يمكن تشغيل ClickHouse Keeper على الخادم نفسه الذي يعمل عليه ClickHouse Server،
      فإننا نوصي بشدة، في بيئات الإنتاج، بتشغيل ClickHouse Keeper على مضيفات مخصصة.
    </Note>

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

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

    ```xml theme={null}
    <macros>
        <shard>01</shard>
        <replica>01</replica>
    </macros>
    ```

    <Note>
      سيُحدَّد كلٌّ منها بشكل مختلف بحسب بنية العنقود.
    </Note>

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

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

    ```xml title="/users.d/users.xml" theme={null}
    <?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`](https://github.com/ClickHouse/examples/blob/main/docker-compose-recipes/recipes/cluster_2S_1R/fs/volumes/clickhouse-01/etc/clickhouse-server/users.d/users.xml) |
    | `fs/volumes/clickhouse-02/etc/clickhouse-server/users.d` | [`users.xml`](https://github.com/ClickHouse/examples/blob/main/docker-compose-recipes/recipes/cluster_2S_1R/fs/volumes/clickhouse-02/etc/clickhouse-server/users.d/users.xml) |

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

    <Note>
      في هذا المثال، يكون كل ملف `users.xml` مطابقًا للآخر على جميع العقد في العنقود.
    </Note>
  </Step>

  <Step title="تكوين ClickHouse Keeper" id="configure-clickhouse-keeper-nodes">
    ### إعداد ClickHouse Keeper

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

    <Note>
      يمكن تشغيل ClickHouse Keeper على أي عقدة في العنقود إلى جانب ClickHouse، رغم أنه
      يُوصى بتشغيله على عقدة مخصصة، مما يتيح التوسّع
      وإدارة عنقود ClickHouse Keeper بشكل مستقل عن عنقود قاعدة البيانات.
    </Note>

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

    ```bash theme={null}
    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`. يجب
    تعديل الأسطر المظللة أدناه بحيث تكون خاصة بكل عقدة:

    ```xml title="/clickhouse-keeper/keeper_config.xml" highlight={12} theme={null}
    <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`](https://github.com/ClickHouse/examples/blob/main/docker-compose-recipes/recipes/cluster_2S_1R/fs/volumes/clickhouse-keeper-01/etc/clickhouse-keeper/keeper_config.xml) |
    | `fs/volumes/clickhouse-keeper-02/etc/clickhouse-keeper` | [`keeper_config.xml`](https://github.com/ClickHouse/examples/blob/main/docker-compose-recipes/recipes/cluster_2S_1R/fs/volumes/clickhouse-keeper-02/etc/clickhouse-keeper/keeper_config.xml) |
    | `fs/volumes/clickhouse-keeper-03/etc/clickhouse-keeper` | [`keeper_config.xml`](https://github.com/ClickHouse/examples/blob/main/docker-compose-recipes/recipes/cluster_2S_1R/fs/volumes/clickhouse-keeper-03/etc/clickhouse-keeper/keeper_config.xml) |

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

    ```xml theme={null}
    <tcp_port>9181</tcp_port>
    <server_id>{id}</server_id>
    ```

    يُستخدم القسم التالي لتكوين الخوادم المشاركة في
    النصاب ضمن [خوارزمية إجماع Raft](https://en.wikipedia.org/wiki/Raft_\(algorithm\)):

    ```xml highlight={6} theme={null}
    <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>
    ```

    <Tip>
      **ClickHouse Cloud يسهّل الإدارة**

      [ClickHouse Cloud](/docs/ar/products/cloud/getting-started/intro)
      يخفف العبء التشغيلي المرتبط بإدارة الأجزاء والنُسخ المتماثلة. تتولى
      المنصة تلقائيًا الإتاحة العالية والنسخ المتماثل وقرارات التوسّع.
      وتكون موارد الحوسبة والتخزين منفصلة، وتتوسع بحسب الطلب من دون الحاجة إلى
      إعداد يدوي أو صيانة مستمرة.

      [اقرأ المزيد](/docs/ar/products/cloud/features/autoscaling/overview)
    </Tip>
  </Step>

  <Step title="اختبر الإعداد" id="test-the-setup">
    تأكد من أن Docker قيد التشغيل على جهازك.
    ابدأ تشغيل الـcluster باستخدام الأمر `docker-compose up` من جذر الدليل `cluster_2S_1R`:

    ```bash theme={null}
    docker-compose up -d
    ```

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

    ```bash theme={null}
    [+] Running 6/6
     ✔ Network cluster_2s_1r_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
    ```

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

    ```bash theme={null}
    # Connect to any node
    docker exec -it clickhouse-01 clickhouse-client
    ```

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

    ```response theme={null}
    cluster_2S_1R node 1 :)
    ```

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

    ```sql title="Query" theme={null}
    SELECT 
        cluster,
        shard_num,
        replica_num,
        host_name,
        port
    FROM system.clusters;
    ```

    ```response title="Response" theme={null}
       ┌─cluster───────┬─shard_num─┬─replica_num─┬─host_name─────┬─port─┐
    1. │ cluster_2S_1R │         1 │           1 │ clickhouse-01 │ 9000 │
    2. │ cluster_2S_1R │         2 │           1 │ clickhouse-02 │ 9000 │
    3. │ default       │         1 │           1 │ localhost     │ 9000 │
       └───────────────┴───────────┴─────────────┴───────────────┴──────┘
    ```

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

    ```sql title="Query" theme={null}
    SELECT *
    FROM system.zookeeper
    WHERE path IN ('/', '/clickhouse')
    ```

    ```response title="Response" theme={null}
       ┌─name───────┬─value─┬─path────────┐
    1. │ task_queue │       │ /clickhouse │
    2. │ sessions   │       │ /clickhouse │
    3. │ clickhouse │       │ /           │
    4. │ keeper     │       │ /           │
       └────────────┴───────┴─────────────┘
    ```

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

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

    <Tip>
      قد تحتاج إلى تثبيت `netcat` حتى تتمكن من إرسال الأمر `mntr` إلى Keeper.
      يُرجى مراجعة صفحة [nmap.org](https://nmap.org/ncat/) للحصول على معلومات التنزيل.
    </Tip>

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

    ```bash theme={null}
    docker exec -it clickhouse-keeper-01  /bin/sh -c 'echo mntr | nc 127.0.0.1 9181'
    ```

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

    ```response title="Response" highlight={9} theme={null}
    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
    ```

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

    ```response title="Response" highlight={9,18-19} theme={null}
    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 يضم شريحتين ونسخة متماثلة واحدة لكل شريحة.
    في الخطوة التالية، ستُنشئ جدولًا في العنقود.
  </Step>

  <Step title="أنشئ قاعدة بيانات" id="creating-a-database">
    الآن بعد أن تحققت من أن العنقود مُعَدّ بشكل صحيح ويعمل، ستعيد إنشاء الجدول نفسه المستخدم في الدليل العملي الخاص بمجموعة البيانات النموذجية [UK property prices](/docs/ar/get-started/sample-datasets/uk-price-paid).
    ويتكوّن من نحو 30 مليون صف لأسعار العقارات المدفوعة
    في إنجلترا وويلز منذ عام 1995.

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

    ```bash theme={null}
    docker exec -it clickhouse-01 clickhouse-client
    docker exec -it clickhouse-02 clickhouse-client
    ```

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

    ```sql title="Query" theme={null}
    SHOW DATABASES;
    ```

    ```response title="Response" theme={null}
       ┌─name───────────────┐
    1. │ INFORMATION_SCHEMA │
    2. │ default            │
    3. │ information_schema │
    4. │ system             │
       └────────────────────┘
    ```

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

    ```sql highlight={2} theme={null}
    CREATE DATABASE IF NOT EXISTS uk 
    ON CLUSTER cluster_2S_1R;
    ```

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

    ```sql theme={null}
    SHOW DATABASES;
    ```

    ```response highlight={6} theme={null}
       ┌─name───────────────┐
    1. │ INFORMATION_SCHEMA │
    2. │ default            │
    3. │ information_schema │
    4. │ system             │
    5. │ uk                 │
       └────────────────────┘
    ```
  </Step>

  <Step title="إنشاء جدول على العنقود" id="creating-a-table">
    الآن بعد أن أُنشئت قاعدة البيانات، ستُنشئ جدولًا.
    شغّل الاستعلام التالي من أي عميل من عملاء المضيف:

    ```sql highlight={2} theme={null}
    CREATE TABLE IF NOT EXISTS uk.uk_price_paid_local
    ON CLUSTER cluster_2S_1R
    (
        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 = MergeTree
    ORDER BY (postcode1, postcode2, addr1, addr2);
    ```

    لاحظ أنه مطابق للاستعلام المستخدم في جملة `CREATE` الأصلية الخاصة بـ
    دليل مجموعة البيانات المثال [UK property prices](/docs/ar/get-started/sample-datasets/uk-price-paid)،
    باستثناء عبارة `ON CLUSTER`.

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

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

    ```sql title="Query" theme={null}
    SHOW TABLES IN uk;
    ```

    ```response title="Response" theme={null}
       ┌─name────────────────┐
    1. │ uk_price_paid_local │
       └─────────────────────┘
    ```

    قبل أن نُدرج بيانات الأسعار المدفوعة في المملكة المتحدة، دعونا نجري تجربة سريعة لمعرفة
    ما الذي يحدث عند إدراج البيانات في جدول عادي من أيٍّ من الخادمين.

    أنشئ قاعدة بيانات وجدولًا اختباريًا باستخدام الاستعلام التالي من أيٍّ من الخادمين:

    ```sql theme={null}
    CREATE DATABASE IF NOT EXISTS test ON CLUSTER cluster_2S_1R;
    CREATE TABLE test.test_table ON CLUSTER cluster_2S_1R
    (
        `id` UInt64,
        `name` String
    )
    ENGINE = MergeTree()
    ORDER BY id;
    ```

    الآن، من `clickhouse-01`، نفّذ استعلام `INSERT` التالي:

    ```sql theme={null}
    INSERT INTO test.test_table (id, name) VALUES (1, 'Clicky McClickface');
    ```

    انتقل إلى `clickhouse-02` ونفّذ استعلام `INSERT` التالي:

    ```sql title="Query" theme={null}
    INSERT INTO test.test_table (id, name) VALUES (1, 'Alexey Milovidov');
    ```

    الآن، شغّل الاستعلام التالي من `clickhouse-01` أو `clickhouse-02`:

    ```sql theme={null}
    -- from clickhouse-01
    SELECT * FROM test.test_table;
    --   ┌─id─┬─name───────────────┐
    -- 1.│  1 │ Clicky McClickface │
    --   └────┴────────────────────┘

    --from clickhouse-02
    SELECT * FROM test.test_table;
    --   ┌─id─┬─name───────────────┐
    -- 1.│  1 │ Alexey Milovidov   │
    --   └────┴────────────────────┘
    ```

    ستلاحظ أنه، بخلاف جدول `ReplicatedMergeTree`، لا يُعاد إلا الصف الذي أُدرج في الجدول على ذلك
    المضيف تحديدًا، وليس كلا الصفين.

    لقراءة البيانات عبر الشاردين، نحتاج إلى واجهة يمكنها التعامل مع الاستعلامات
    عبر جميع الشاردات، مع دمج البيانات من كلا الشاردين عندما ننفّذ استعلامات select
    عليها، أو إدراج البيانات في كلا الشاردين عندما ننفّذ استعلامات insert.

    في ClickHouse تُسمّى هذه الواجهة **جدولًا موزعًا**، وننشئها باستخدام
    محرك الجدول [`Distributed`](/docs/ar/reference/engines/table-engines/special/distributed). لنلقِ نظرة على كيفية عمله.
  </Step>

  <Step title="إنشاء جدول موزّع" id="create-distributed-table">
    أنشئ جدولًا موزّعًا باستخدام الاستعلام التالي:

    ```sql theme={null}
    CREATE TABLE test.test_table_dist ON CLUSTER cluster_2S_1R AS test.test_table
    ENGINE = Distributed('cluster_2S_1R', 'test', 'test_table', rand())
    ```

    في هذا المثال، اختيرت الدالة `rand()` كمفتاح للتجزئة بحيث
    تتوزع عمليات الإدراج عشوائيًا على الأجزاء.

    الآن نفّذ استعلامًا على الجدول الموزّع من أيٍّ من المضيفين، وستحصل
    على كلا الصفين اللذين أُدرجا على المضيفين كليهما، بخلاف مثالنا السابق:

    ```sql theme={null}
    SELECT * FROM test.test_table_dist;
    ```

    ```response theme={null}
       ┌─id─┬─name───────────────┐
    1. │  1 │ Alexey Milovidov   │
    2. │  1 │ Clicky McClickface │
       └────┴────────────────────┘
    ```

    لنفعل الأمر نفسه مع بيانات أسعار العقارات في المملكة المتحدة. من أيٍّ من الأجهزة المضيفة التي تشغّل العميل،
    شغّل الاستعلام التالي لإنشاء جدول موزّع باستخدام الجدول الحالي
    الذي أنشأناه سابقًا باستخدام `ON CLUSTER`:

    ```sql theme={null}
    CREATE TABLE IF NOT EXISTS uk.uk_price_paid_distributed
    ON CLUSTER cluster_2S_1R
    ENGINE = Distributed('cluster_2S_1R', 'uk', 'uk_price_paid_local', rand());
    ```
  </Step>

  <Step title="إدراج البيانات في جدول موزّع" id="inserting-data-into-distributed-table">
    الآن اتصل بأيٍّ من المضيفَين وأدرج البيانات:

    ```sql theme={null}
    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;
    ```

    بمجرد إدراج البيانات، يمكنك التحقق من عدد الصفوف باستخدام الجدول الموزع:

    ```sql title="Query" theme={null}
    SELECT count(*)
    FROM uk.uk_price_paid_distributed
    ```

    ```response title="Response" theme={null}
       ┌──count()─┐
    1. │ 30212555 │ -- 30.21 million
       └──────────┘
    ```

    إذا نفّذت الاستعلام التالي على أيٍّ من المضيفَين، ستلاحظ أن البيانات توزّعت بشكل متساوٍ إلى حدٍّ ما عبر الأجزاء (علمًا بأن اختيار الجزء الذي تُدرج فيه البيانات كان عشوائيًا باستخدام `rand()`، لذا قد تختلف النتائج لديك):

    ```sql theme={null}
    -- from clickhouse-01
    SELECT count(*)
    FROM uk.uk_price_paid_local
    --    ┌──count()─┐
    -- 1. │ 15107353 │ -- 15.11 million
    --    └──────────┘

    --from clickhouse-02
    SELECT count(*)
    FROM uk.uk_price_paid_local
    --    ┌──count()─┐
    -- 1. │ 15105202 │ -- 15.11 million
    --    └──────────┘
    ```

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

    ```bash theme={null}
    docker stop clickhouse-01
    ```

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

    ```bash theme={null}
    docker-compose ps
    ```

    ```response title="Response" theme={null}
    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-02` نفِّذ نفس استعلام select الذي أجريناه سابقًا على الجدول الموزَّع:

    ```sql theme={null}
    SELECT count(*)
    FROM uk.uk_price_paid_distributed
    ```

    ```response title="Response" highlight={6} theme={null}
    Received exception from server (version 25.5.2):
    Code: 279. DB::Exception: Received from localhost:9000. DB::Exception: All connection tries failed. Log:

    Code: 32. DB::Exception: Attempt to read after eof. (ATTEMPT_TO_READ_AFTER_EOF) (version 25.5.2.47 (official build))
    Code: 209. DB::NetException: Timeout: connect timed out: 192.168.7.1:9000 (clickhouse-01:9000, 192.168.7.1, local address: 192.168.7.2:37484, connection timeout 1000 ms). (SOCKET_TIMEOUT) (version 25.5.2.47 (official build))
    Code: 198. DB::NetException: Not found address of host: clickhouse-01: (clickhouse-01:9000, 192.168.7.1, local address: 192.168.7.2:37484). (DNS_ERROR) (version 25.5.2.47 (official build))

    : While executing Remote. (ALL_CONNECTION_TRIES_FAILED)
    ```

    للأسف، مجموعتنا ليست متسامحة مع الأعطال. إذا تعطّل أحد المضيفين، تُعدّ المجموعة غير سليمة ويفشل الاستعلام، خلافًا للجدول المُكرَّر الذي رأيناه في [المثال السابق](/docs/ar/guides/oss/deployment-and-scaling/examples/1-shard-2-replicas)، والذي كنّا قادرين فيه على إدراج البيانات حتى عند تعطّل أحد المضيفين.
  </Step>
</Steps>

<div id="conclusion">
  ## الخاتمة
</div>

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

أما العيب الرئيسي لطوبولوجيا هذا العنقود فهو، بطبيعة الحال، أن فقدان أحد
المضيفين يجعلنا غير قادرين على معالجة الاستعلامات.

في [المثال التالي](/docs/ar/guides/oss/deployment-and-scaling/examples/2-shards-2-replicas)، سنلقي نظرة على كيفية
إعداد عنقود يضم شاردين ونسختين متماثلتين، بما يوفّر قابلية التوسع
وتحمّل الأعطال.
