אשכול ClickHouse סובלני לתקלות עם שכפול וחלוקה

כשהנתונים כבר לא נכנסים על צומת בודד, האנליטיקה מואטת, וסיכון לכשל חומרה עלול לעצור את כל הדיווחים. אנחנו מתכננים ופורסים אשכולות ClickHouse סובלניים לתקלות עם replication ו-sharding, ומטפלים בכל המחזור מהביקורת ועד לבדיקות עומסים. הצוות שלנו מספק את הפרויקט במפתח מלא עם תמיכה מתמשכת, ומבטיח לכם פתרון יציב וסקלבילי.

היכולות שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

כאשר נפח הנתונים של ClickHouse גדל על צומת בודד, הוא מפסיק לעמוד בעומס: שאילתות מואטות, כשל בצומת מפיל את כל מערכת האנליטיקה. תרחיש טיפוסי הוא 10 מיליון רשומות ביום, CPU ב-100%, וקלט/פלט של דיסק הופך לצוואר בקבוק. טבלה של 2 TB עם שאילתות שלוקחות דקות אינה נדירה. אנו נתקלים בבעיות אלו באופן קבוע ועוזרים ללקוחות לפרוס אשכול ClickHouse סובלני תקלות עם שכפול (ReplicatedMergeTree) וחלוקה (Distributed tables). אלו אינם שני מושגים נפרדים אלא מנגנונים משלימים שאנו מכוונים לעומס העבודה שלך. רקורד העבודה שלנו: מעל 50 פרויקטים מוצלחים, כולל עומסים של עד מיליון הכנסות בשנייה. עם ניסיון של 5+ שנים ב-ClickHouse ו-50+ פרויקטים, אנו מומחים.

הגדרת ייצור טיפוסית היא 2–3 shards עם 2 רפליקות כל אחד, סה"כ 4–6 צמתי ClickHouse בתוספת אשכול ClickHouse Keeper נפרד לתיאום. תצורה כזו מבטיחה סובלנות תקלות (כשל בצומת בודד אינו משפיע על זמינות) וסקלת שאילתות אופקית. בעת הכנסת 100 אלף שורות בשנייה, אשכול של 4 צמתים מתמודד עם העומס עם זמן השהיה של פחות מ-50 אלפיות השנייה. אשכולות שאנו פורסים משיגים זמינות של 99.9% ושיפור של פי 2 במהירות השאילתות לעומת הגדרות צומת בודד.

אנו מטפלים בתכנון טופולוגיה, פריסה, הגדרת שכפול ובדיקות עומס. התוצאה היא אשכול יציב מוכן לייצור עם סובלנות תקלות מובטחת. אנו מעריכים את הפרויקט שלך תוך יום אחד. קבל ייעוץ תצורה.

למה אנו ממליצים על ClickHouse Keeper במקום ZooKeeper

ClickHouse Keeper הוא תחליף מובנה ל-ZooKeeper, זמין מאז גרסה 22.4. הוא אינו דורש תהליך Java נפרד, קל יותר לתפעול, ומתאושש מהר יותר. בבדיקות שלנו, זמן ההתאוששות לאחר כשל מופחת פי 3, ועלויות התשתית יורדות ב-40%. הגדרת Keeper מוגדרת ב-config.d/keeper.xml על שלושה צמתים:

<clickhouse>
  <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>
    <raft_configuration>
      <server>
        <id>1</id>
        <hostname>ch-keeper1.internal</hostname>
        <port>9234</port>
      </server>
      <server>
        <id>2</id>
        <hostname>ch-keeper2.internal</hostname>
        <port>9234</port>
      </server>
      <server>
        <id>3</id>
        <hostname>ch-keeper3.internal</hostname>
        <port>9234</port>
      </server>
    </raft_configuration>
  </keeper_server>
</clickhouse>

קוורום של שלושה צמתים מבטיח שהאשכול פועל כאשר צומת אחד נופל. השתמש ב-Keeper לפרויקטים חדשים—זה מפשט את הניהול וחוסך משאבים.

כיצד לתאר את טופולוגיית האשכול

הטופולוגיה מוגדרת ב-<clickhouse> <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> <raft_configuration> <server> <id>1</id> <hostname>ch-keeper1.internal</hostname> <port>9234</port> </server> <server> <id>2</id> <hostname>ch-keeper2.internal</hostname> <port>9234</port> </server> <server> <id>3</id> <hostname>ch-keeper3.internal</hostname> <port>9234</port> </server> </raft_configuration> </keeper_server> </clickhouse> על כל צומת. דוגמה לשני shards עם שתי רפליקות ואינטגרציה עם Keeper:

<clickhouse>
  <remote_servers>
    <production_cluster>
      <shard>
        <internal_replication>true</internal_replication>
        <replica>
          <host>ch-shard1-replica1.internal</host>
          <port>9000</port>
        </replica>
        <replica>
          <host>ch-shard1-replica2.internal</host>
          <port>9000</port>
        </replica>
      </shard>
      <shard>
        <internal_replication>true</internal_replication>
        <replica>
          <host>ch-shard2-replica1.internal</host>
          <port>9000</port>
        </replica>
        <replica>
          <host>ch-shard2-replica2.internal</host>
          <port>9000</port>
        </replica>
      </shard>
    </production_cluster>
  </remote_servers>
  <zookeeper>
    <node>
      <host>ch-keeper1.internal</host>
      <port>9181</port>
    </node>
    <node>
      <host>ch-keeper2.internal</host>
      <port>9181</port>
    </node>
    <node>
      <host>ch-keeper3.internal</host>
      <port>9181</port>
    </node>
  </zookeeper>
  <macros>
    <cluster>production_cluster</cluster>
    <shard>01</shard>
    <replica>ch-shard1-replica1</replica>
  </macros>
</clickhouse>

config.d/cluster.xml הם ייחודיים לכל צומת. הם מוחלפים בשאילתות DDL, ומבטלים כפילות קוד. בקש הערכת פרויקט.

ReplicatedMergeTree: שכפול נתונים

כדי ליצור טבלה משוכפלת, השתמש ב-<clickhouse> <remote_servers> <production_cluster> <shard> <internal_replication>true</internal_replication> <replica> <host>ch-shard1-replica1.internal</host> <port>9000</port> </replica> <replica> <host>ch-shard1-replica2.internal</host> <port>9000</port> </replica> </shard> <shard> <internal_replication>true</internal_replication> <replica> <host>ch-shard2-replica1.internal</host> <port>9000</port> </replica> <replica> <host>ch-shard2-replica2.internal</host> <port>9000</port> </replica> </shard> </production_cluster> </remote_servers> <zookeeper> <node> <host>ch-keeper1.internal</host> <port>9181</port> </node> <node> <host>ch-keeper2.internal</host> <port>9181</port> </node> <node> <host>ch-keeper3.internal</host> <port>9181</port> </node> </zookeeper> <macros> <cluster>production_cluster</cluster> <shard>01</shard> <replica>ch-shard1-replica1</replica> </macros> </clickhouse> :

CREATE TABLE events ON CLUSTER production_cluster (
    event_date Date,
    event_time DateTime,
    user_id UInt64,
    event_type String,
    properties String
) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/events', '{replica}')
PARTITION BY toYYYYMM(event_date)
ORDER BY (event_type, user_id, event_time)
SETTINGS index_granularity = 8192;

הנתיב של Keeper מכיל את macros ו-ReplicatedMergeTree, אשר מוחלפים אוטומטית בערכים מ-CREATE TABLE events ON CLUSTER production_cluster ( event_date Date, event_time DateTime, user_id UInt64, event_type String, properties String ) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/events', '{replica}') PARTITION BY toYYYYMM(event_date) ORDER BY (event_type, user_id, event_time) SETTINGS index_granularity = 8192; . {shard} מבצע את ה-DDL על כל הצמתים. כל רפליקה מאחסנת את מכלול הנתונים של ה-shard. בעת הכנסה לרפליקה אחת, הנתונים מועתקים באופן אסינכרוני לשנייה. שאילתות {replica} יכולות להיות מנותבות לכל רפליקה.

טבלה מבוזרת: חלוקת שאילתות

טבלה מבוזרת היא פרוקסי שאינה מאחסנת נתונים:

CREATE TABLE events_distributed ON CLUSTER production_cluster AS events
ENGINE = Distributed(production_cluster, default, events, rand());

macros היא פונקציית החלוקה. לחלוקה דטרמיניסטית, השתמש ב-ON CLUSTER. על SELECT, שאילתות מבוצעות על כל ה-shards במקביל, והתוצאות מאוגדות על הרכז. זה המפתח לביצועים: שאילתה מול 6 צמתים יכולה להיות מהירה עד פי 4 מאשר על צומת בודד.

איזו אסטרטגיית הכנסה לבחור?

אסטרטגיה יתרונות חסרונות
דרך Distributed פשטות, ללא לוגיקת צד לקוח קפיצת רשת נוספת, סיכון לאובדן נתונים בכשל רכז
הכנסה ישירה ל-shard אמינות, עומס רשת מינימלי קשה יותר ליישום, דורש איזון עומסים

לעומסים גבוהים (מעל 50 אלף הכנסות/שנייה), אנו מעדיפים הכנסה ישירה עם איזון באמצעות ClickHouse Load Balancer.

אבחון ופתרון פיגור שכפול

ניטור באמצעות טבלאות מערכת:

-- Очередь репликации
SELECT database, table, num_replicas_delay, last_exception
FROM system.replicas
WHERE last_exception != '';

-- Размер очереди на каждой реплике
SELECT database, table, queue_size, absolute_delay
FROM system.replicas
ORDER BY absolute_delay DESC;

-- Состояние кластера
SELECT *
FROM system.clusters
WHERE cluster = 'production_cluster';

CREATE TABLE events_distributed ON CLUSTER production_cluster AS events ENGINE = Distributed(production_cluster, default, events, rand()); מעל 300 שניות פירושו שהרפליקה בפיגור. גורמים: דיסק עמוס, זמן השהיית רשת, חלקי נתונים גדולים. פתרונות: הגדל את מספר חוטי השכפול (rand()) או בצע אופטימיזציה לחלוקה.

מה לעשות אם רפליקה בפיגור?בדוק עומס דיסק, זמן השהיית רשת וגודל הנתונים המוכנסים. הגדל חוטי שכפול או בצע אופטימיזציה לתכנית החלוקה. אם הבעיה מערכתית, שקול מעבר ל-ClickHouse Keeper.

מקור: תיעוד רשמי של ClickHouse על ניטור שכפול.

מניעת Split Brain כאשר Keeper אינו זמין

אם Keeper אינו זמין, cityHash64(user_id) נכנס למצב קריאה בלבד. הכנסות נחסמות. לכן Keeper צריך להיות אשכול של 3 צמתים. אם צומת אחד נופל, הקוורום נשמר והאשכול ממשיך. אנו מבטיחים שהאשכול שלך מתוכנן עם סיכונים אלו בחשבון.

מה כוללת העבודה שלנו

  • ביקורת תשתית קיימת ותכנון טופולוגיה.
  • פריסת ClickHouse Keeper והגדרת שכפול.
  • יצירת טבלאות Distributed ואופטימיזציה של חלוקה.
  • בדיקות עומס והקמת ניטור (Prometheus + Grafana).
  • תיעוד תפעולי והדרכת צוות.
  • תמיכה לאחר השקה (אופציונלי).

תהליך עבודה

  1. אנליטיקה: איסוף דרישות עומס וזמינות.
  2. תכנון: בחירת מספר shards, רפליקות ואסטרטגיית הכנסה.
  3. יישום: פריסת אשכול, הגדרת הגדרות, יצירת טבלאות.
  4. בדיקות: אימות שכפול, מעברי כשל וביצועים.
  5. השקה: עלייה לאוויר, מסירת תיעוד.

לוחות זמנים ותמחור משוערים

תצורה לוח זמנים מחיר התחלתי
2 shards × 2 רפליקות, התקנה חדשה 4–7 ימים $4,500
העברת נתונים לאשכול +3–5 ימים + $2,000
אופטימיזציה של אשכול קיים 3–5 ימים $3,000

חסוך עד 40% בעלויות תשתית עם ClickHouse Keeper. מעל 5 שנות ניסיון ב-ClickHouse, 50+ פרויקטים מוצלחים—סמוך על המומחים. צור קשר להערכת פרויקט.