הגדרת Apache Cassandra ליישומי אינטרנט בעומס גבוה

עומסים גבוהים על יישום web פוגעים פעמים רבות במסד הנתונים, שאינו עומד בקצב הבקשות ומתחיל להאט. אנחנו מגדירים Apache Cassandra מוכן לשימוש — מתכננים את סכמת הנתונים, מגדירים את ה-cluster ומבצעים אופטימיזציה למשימה שלך. הצוות שלנו מטפל בכל מחזור העבודה ומבטיח פעילות יציבה של המערכת עם תמיכה מתמשכת.

פיתוח ותחזוקה של כל סוגי האתרים:

אתרי מידע או יישומי אינטרנט
אתרי תדמית, דפי נחיתה, אתרי חברה, קטלוגים מקוונים, חידונים, אתרי קידום, בלוגים, מקורות חדשות, פורטלי מידע, פורומים, אגרגטורים
אתרי מסחר אלקטרוני או יישומי אינטרנט
חנויות מקוונות, פורטלי B2B, שווקים, בורסות מקוונות, אתרי קאשבק, בורסות, פלטפורמות דרופשיפינג, מנתחי מוצרים
יישומי אינטרנט לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, פורטלים ארגוניים, מערכות ניהול ייצור, מנתחי מידע
אתרי שירות אלקטרוני או יישומי אינטרנט
פלטפורמות מודעות, בתי ספר מקוונים, בתי קולנוע מקוונים, בוני אתרים, פורטלים לשירותים אלקטרוניים, פלטפורמות אירוח וידאו, פורטלים נושאיים

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

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
הגדרת Apache Cassandra ליישומי אינטרנט בעומס גבוה
מורכב
~3-5 ימים

הכישורים שלנו:

שאלות נפוצות

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

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1365
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113
  • פיתוח אתר עבור SBH Partners
    פיתוח אתר עבור SBH Partners
    1201
  • פיתוח אתר עבור Red Pear
    פיתוח אתר עבור Red Pear
    619

הגדרת Apache Cassandra עבור יישום web כוללת יותר מסתם התקנת חבילה. ללא עיצוב סכמה נכון ותצורת cluster, תיתקל בשאילתות איטיות, מחיצות חמות, ופעילות לא יציבה תחת עומס. במשך 5 שנים, הגדרנו את Cassandra עבור 30+ פרויקטים: זרמי אירועים, מדדים, ולוגים. הטעות הנפוצה ביותר היא מפתח ראשי שגוי. התעלמות מ-compaction וזיכרון לא מספק עבור memtables מובילה לירידת ביצועים של פי 2–3. הגדרת Cassandra נכונה מההתחלה חוסכת שבועות של עבודה חוזרת. הנה הטכניקות המוכחות שלנו.

היכן Cassandra חיונית

סדרות זמן עם מיליוני אירועים בשנייה, פידים של פעילות, מערכות לוגינג, טלמטריה של IoT — תרחישים הדורשים כתיבות מהירות ובנפח גבוה. Netflix, Discord, ו-Apple משתמשות ב-Cassandra בדיוק לשם כך. Discord מאחסנת טריליוני הודעות. עבור OLTP עם טרנזקציות מורכבות, היא אינה מתאימה. אנו משתמשים ב-Cassandra לאחסון מדדים ולוגים: היא מספקת סקלביליות כתיבה לינארית וסובלנות לתקלות ללא נקודת כשל יחידה.

כיצד להתקין ולהגדיר את Cassandra 4.1

התקנת Cassandra 4.1:

echo "deb https://debian.cassandra.apache.org 41x main" > /etc/apt/sources.list.d/cassandra.sources.list
curl https://downloads.apache.org/cassandra/KEYS | apt-key add -
apt update && apt install -y cassandra

לאחר ההתקנה, ערוך את echo "deb https://debian.cassandra.apache.org 41x main" > /etc/apt/sources.list.d/cassandra.sources.list curl https://downloads.apache.org/cassandra/KEYS | apt-key add - apt update && apt install -y cassandra :

---
cluster_name: 'MyAppCluster' # Сеть
listen_address: 10.0.0.1
rpc_address: 10.0.0.1
seeds: "10.0.0.1,10.0.0.2,10.0.0.3"
# Директории
data_file_directories:
  - /var/lib/cassandra/data
commitlog_directory: /var/lib/cassandra/commitlog # отдельный диск для скорости
hints_directory: /var/lib/cassandra/hints
saved_caches_directory: /var/lib/cassandra/saved_caches
# Производительность
concurrent_reads: 32
concurrent_writes: 32
concurrent_counter_writes: 16
memtable_heap_space: 2048
compaction_throughput_mb_per_sec: 64
# Репликация и консистентность
endpoint_snitch: GossipingPropertyFileSnitch
# JVM (в jvm11-server.options)
num_tokens: 256

בנוסף, הגדר את JVM כדי למנוע השהיות GC ארוכות:

# /etc/cassandra/jvm11-server.options
-Xms8G
-Xmx8G
-XX:+UseG1GC
-XX:G1RSetUpdatingPauseTimePercent=5
-XX:MaxGCPauseMillis=300
-XX:InitiatingHeapOccupancyPercent=70

השוואת אסטרטגיות compaction

אסטרטגיה מטרה מתי להשתמש
SizeTieredCompactionStrategy ברירת מחדל אפשרות אוניברסלית, מתאימה לרוב המקרים
TimeWindowCompactionStrategy סדרות זמן נתונים עם TTL, פידים של אירועים — מפחיתה את מספר הקבצים
LeveledCompactionStrategy עדכונים תכופים מערכות עם כתיבות מרובות, דורשת יותר שטח דיסק

בחירת ה-compaction משפיעה ישירות על ביצועי הקריאה והכתיבה. לדוגמה, TimeWindowCompactionStrategy מפחיתה את מספר ה-SSTables פי 2–3 בהשוואה ל-SizeTieredCompactionStrategy בעבודה עם סדרות זמן. אנו ממליצים על TimeWindowCompactionStrategy עבור נתונים עם TTL, ועל LeveledCompactionStrategy עבור תרחישים עם עדכונים אינטנסיביים.

באיזו אסטרטגיית compaction לבחור?

בסס את הבחירה על מאפייני הנתונים. אם לנתונים יש TTL והם נכתבים בקצב קבוע — TimeWindowCompactionStrategy. עבור עדכונים ומחיקות תכופים — LeveledCompactionStrategy. SizeTieredCompactionStrategy היא בחירה בטוחה אם אינך בטוח.

מדוע בחירת מפתח מחיצה נכון חשובה?

מפתח המחיצה קובע את התפלגות הנתונים בין הצמתים. אם נבחר בצורה שגויה, חלק מהצמתים יהיו עמוסים בעוד אחרים יישארו ריקים. לדוגמה, עבור הטבלה cassandra.yaml אנו משתמשים ב-cluster_name: 'MyAppCluster' # Сеть listen_address: 10.0.0.1 rpc_address: 10.0.0.1 seeds: "10.0.0.1,10.0.0.2,10.0.0.3" # Директории data_file_directories: - /var/lib/cassandra/data commitlog_directory: /var/lib/cassandra/commitlog # отдельный диск для скорости hints_directory: /var/lib/cassandra/hints saved_caches_directory: /var/lib/cassandra/saved_caches # Производительность concurrent_reads: 32 concurrent_writes: 32 concurrent_counter_writes: 16 memtable_heap_space: 2048 compaction_throughput_mb_per_sec: 64 # Репликация и консистентность endpoint_snitch: GossipingPropertyFileSnitch # JVM (в jvm11-server.options) num_tokens: 256 — זה מבטיח התפלגות אחידה. עבור סדרות זמן (טבלה # /etc/cassandra/jvm11-server.options -Xms8G -Xmx8G -XX:+UseG1GC -XX:G1RSetUpdatingPauseTimePercent=5 -XX:MaxGCPauseMillis=300 -XX:InitiatingHeapOccupancyPercent=70 ), מפתח מורכב user_events מקבץ מדדים לפי שירות וחלון זמן. לעולם אל תשתמש בעמודות עם ערכים ייחודיים מעטים (boolean או enum) — זה מוביל למחיצות חמות.

סכמת נתונים — עיצוב מונחה שאילתות

-- Keyspace с репликацией
CREATE KEYSPACE myapp WITH replication = { 'class': 'NetworkTopologyStrategy', 'dc1': 3 } AND durable_writes = true;
USE myapp;
-- Лента событий пользователя
CREATE TABLE user_events (
    user_id uuid,
    occurred_at timestamp,
    event_id uuid,
    event_type text,
    payload text,
    PRIMARY KEY ((user_id), occurred_at, event_id)
) WITH CLUSTERING ORDER BY (occurred_at DESC) AND compaction = {'class': 'TimeWindowCompactionStrategy', 'compaction_window_unit': 'DAYS', 'compaction_window_size': 7} AND default_time_to_live = 7776000;
-- Статистика по пользователям
CREATE TABLE user_stats (
    user_id uuid PRIMARY KEY,
    total_orders counter,
    total_spent counter,
    last_active timestamp
);
-- Временные ряды метрик
CREATE TABLE metrics (
    service text,
    bucket timestamp,
    metric_name text,
    ts timestamp,
    value double,
    PRIMARY KEY ((service, bucket, metric_name), ts)
) WITH CLUSTERING ORDER BY (ts DESC) AND compaction = {'class': 'TimeWindowCompactionStrategy', 'compaction_window_unit': 'HOURS', 'compaction_window_size': 1};

אינטגרציה עם backend של Node.js

import cassandra from 'cassandra-driver'

const client = new cassandra.Client({
  contactPoints: ['10.0.0.1', '10.0.0.2', '10.0.0.3'],
  localDataCenter: 'dc1',
  keyspace: 'myapp',
  credentials: {
    username: 'cassandra',
    password: process.env.CASSANDRA_PASSWORD!
  },
  pooling: {
    coreConnectionsPerHost: {
      [cassandra.types.distance.local]: 3,
      [cassandra.types.distance.remote]: 1
    }
  },
  socketOptions: {
    readTimeout: 12000
  }
})

await client.connect()

const insertEvent = await client.prepare(`
  INSERT INTO user_events (user_id, occurred_at, event_id, event_type, payload)
  VALUES (?, ?, ?, ?, ?)
`)

const selectEvents = await client.prepare(`
  SELECT * FROM user_events
  WHERE user_id = ? AND occurred_at >= ? AND occurred_at <= ?
  ORDER BY occurred_at DESC
  LIMIT ?
`)

async function writeEvents(events: UserEvent[]) {
  const batch = events.map(e => ({
    query: insertEvent,
    params: [
      cassandra.types.Uuid.fromString(e.userId),
      new Date(e.occurredAt),
      cassandra.types.TimeUuid.now(),
      e.eventType,
      JSON.stringify(e.payload)
    ]
  }))
  await client.batch(batch, { prepare: true, logged: false })
}

async function* fetchEvents(userId: string, from: Date, to: Date) {
  const options = { prepare: true, fetchSize: 1000 }
  let pageState: Buffer | undefined
  do {
    const result = await client.execute(
      selectEvents,
      [cassandra.types.Uuid.fromString(userId), from, to, 1000],
      { ...options, pageState }
    )
    yield result.rows
    pageState = result.pageState as Buffer | undefined
  } while (pageState)
}

רמות עקביות

רמה מהירות אמינות מקרה שימוש
ONE מהירה נמוכה אנליטיקה, cache
LOCAL_QUORUM בינונית גבוהה פעולות כתיבה
QUORUM איטית מקסימלית נתונים קריטיים
const { types: { consistencies } } = cassandra
await client.execute(insertEvent, params, { consistency: consistencies.localQuorum })
await client.execute(selectEvents, params, { consistency: consistencies.one })
await client.execute(criticalQuery, params, { consistency: consistencies.quorum })

ניטור ואבחון

nodetool status nodetool tpstats nodetool cfstats myapp.user_events nodetool compactionstats nodetool cleanup myapp 

הפעל רישום שאילתות איטיות ב-user_id: metrics.

טעויות נפוצות והפתרונות שלהן

  • מחיצות חמות עקב מפתח שגוי: השתמש במפתחות מורכבים עם קרדינליות גבוהה. הימנע מעמודות עם ערכים מעטים.
  • צריכת זיכרון גבוהה: הפחת את (service, bucket, metric_name) או עבור מ-G1GC ל-ParallelGC.
  • כתיבות איטיות: בדוק את הדיסק עבור commitlog — השתמש ב-SSD נפרד. הגדל את -- Keyspace с репликацией CREATE KEYSPACE myapp WITH replication = { 'class': 'NetworkTopologyStrategy', 'dc1': 3 } AND durable_writes = true; USE myapp; -- Лента событий пользователя CREATE TABLE user_events ( user_id uuid, occurred_at timestamp, event_id uuid, event_type text, payload text, PRIMARY KEY ((user_id), occurred_at, event_id) ) WITH CLUSTERING ORDER BY (occurred_at DESC) AND compaction = {'class': 'TimeWindowCompactionStrategy', 'compaction_window_unit': 'DAYS', 'compaction_window_size': 7} AND default_time_to_live = 7776000; -- Статистика по пользователям CREATE TABLE user_stats ( user_id uuid PRIMARY KEY, total_orders counter, total_spent counter, last_active timestamp ); -- Временные ряды метрик CREATE TABLE metrics ( service text, bucket timestamp, metric_name text, ts timestamp, value double, PRIMARY KEY ((service, bucket, metric_name), ts) ) WITH CLUSTERING ORDER BY (ts DESC) AND compaction = {'class': 'TimeWindowCompactionStrategy', 'compaction_window_unit': 'HOURS', 'compaction_window_size': 1}; .

כמה זמן אורך הגדרה מלאה?

פרויקט טיפוסי עם שלושה צמתים ואינטגרציה אורך 2–3 שבועות. זה כולל ביקורת דרישות, עיצוב סכמה, פריסת cluster, כוונון תצורה, וכתיבת adapter ל-backend. Clusters מורכבים עם מרכזי נתונים מרובים עשויים לארוך עד 5 שבועות. קבל הערכה מדויקת לפרויקט שלך — צור קשר.

המקרים והערבויות שלנו

השלמנו מעל 30 פרויקטים עם Cassandra, כולל מערכות מדדים לפלטפורמת פרסום (100 מיליון אירועים ביום) ופידים של פעילות עבור שירות SaaS. בכל פרויקט, אנו מבטיחים פעילות cluster יציבה למשך חודש לאחר המסירה. למהנדסים שלנו יש ניסיון של 5+ שנים עם Cassandra וטכנולוגיות קשורות. צור קשר לייעוץ — נדון בארכיטקטורה שלך ללא עלות.

מה כלול בהגדרה turnkey

  • ביקורת הארכיטקטורה הנוכחית ודרישות העומס
  • עיצוב סכמת נתונים (עיצוב מונחה שאילתות)
  • פריסת cluster (bare-metal / cloud / Docker)
  • אופטימיזציה של import cassandra from 'cassandra-driver' const client = new cassandra.Client({ contactPoints: ['10.0.0.1', '10.0.0.2', '10.0.0.3'], localDataCenter: 'dc1', keyspace: 'myapp', credentials: { username: 'cassandra', password: process.env.CASSANDRA_PASSWORD! }, pooling: { coreConnectionsPerHost: { [cassandra.types.distance.local]: 3, [cassandra.types.distance.remote]: 1 } }, socketOptions: { readTimeout: 12000 } }) await client.connect() const insertEvent = await client.prepare(` INSERT INTO user_events (user_id, occurred_at, event_id, event_type, payload) VALUES (?, ?, ?, ?, ?) `) const selectEvents = await client.prepare(` SELECT * FROM user_events WHERE user_id = ? AND occurred_at >= ? AND occurred_at <= ? ORDER BY occurred_at DESC LIMIT ? `) async function writeEvents(events: UserEvent[]) { const batch = events.map(e => ({ query: insertEvent, params: [ cassandra.types.Uuid.fromString(e.userId), new Date(e.occurredAt), cassandra.types.TimeUuid.now(), e.eventType, JSON.stringify(e.payload) ] })) await client.batch(batch, { prepare: true, logged: false }) } async function* fetchEvents(userId: string, from: Date, to: Date) { const options = { prepare: true, fetchSize: 1000 } let pageState: Buffer | undefined do { const result = await client.execute(selectEvents, [cassandra.types.Uuid.fromString(userId), from, to, 1000], { ...options, pageState }) yield result.rows pageState = result.pageState as Buffer | undefined } while (pageState) } , JVM, והגדרות רשת
  • אינטגרציית backend (Node.js, Python, Go)
  • תיעוד סכמה והוראות תפעול
  • הדרכת צוות והמלצות תפעוליות
  • פעילות cluster יציבה מובטחת למשך חודש לאחר המסירה

הזמן כוונון Cassandra לפרויקט שלך — קבל ייעוץ ממהנדס עם 5 שנות ניסיון.