פיתוח מערכת אחסון נתוני tick: היכן הזרימה נשברת
אחסון נתוני tick נשבר לא בשיא, אלא בחוסר הסימטריה של העומס: זרם המחירים גדל במדרגות — בפתיחת סשנים, בפרסום נתונים סטטיסטיים — בעוד שפייפליין הכתיבה נשאר אחיד ונקודתי. ברגע שקצב הכניסה עולה על קיבולת באפר הקליטה, המקור מתחיל להשליך הודעות, ובארכיון מופיעים פערים בכתיבה.
הערמומיות היא שהם לא נראים מיד: הפער צף מאוחר יותר, כאשר בונים נרות מהארכיון או מריצים אסטרטגיית מסחר.
השהיית הכתיבה בדרך כלל מתחבאת במקום אחד — בשטיפת הבאפר הנצבר לדיסק. אם קליטת הנתונים והכתיבה פועלות באותו thread, כל סנכרון עם הדיסק עוצר את קליטת המחירים החדשים, וככל שהמנה גדולה יותר, ההפוגה ארוכה יותר.
הפרדה בין קליטה לכתיבה באמצעות תור ושטיפה מקובצת עוזרת, אבל לכל הפרדה כזו יש סף: מעבר לו התור גדל מהר יותר מקצב ריקונו, והאובדנים חוזרים.
נקודת הכשל השלישית — פרגמנטציה של הארכיון. כל עוד הכלים והימים בודדים, הקבצים נפתחים באופן אקראי ומהר; כשהספירה מגיעה למיליוני מקטעים, התקורה של החיפוש מתחילה לעלות על זמן הקריאה המועילה.
חלוקה למחיצות לפי תאריכים וטיקרים מסירה חלק מהבעיה, אבל דורשת מדיניות דחיסה ומחיקה הוגנת, אחרת הנפח גדל מהר יותר מהנתונים עצמם.
ארכיון בכתיבה עצמית כמעט תמיד התחיל ממשימה אחת: תהליך אחד, כלי אחד, פלטפורמה אחת. כל מקור חדש, גידול בעומק ההיסטוריה או דרישה לשחזור מוסיף ענף קוד נוסף בלי מודל אמינות כולל — המערכת מאבדת את יכולת החיזוי. נפרק כיצד זה נסגר בכל קטע של הפייפליין.
מה נותן אחסון ייעודי: אפקט במדדים מדידים
אחסון ייעודי משנה לא את הנוחות של העבודה עם הארכיון, אלא מדדים מדידים: כמה עסקאות באמת הגיעו לכתיבה, תוך כמה זמן מוחזר טווח היסטורי וכמה מהר הצומת חוזר לפעולה לאחר כשל. בדיוק את המדדים האלה אנחנו מביאים לבדיקת הקבלה.
שלמות הנתונים ההיסטוריים. על קבצים שטוחים ניתוק הקשר או הפעלה מחדש של התהליך מותירים חורים, שמתגלים כבר בעת השוואת האסטרטגיה. קו הכתיבה עם באפר מקומי ואישור כתיבה סוגר את הפער בזרימה לאחר התחברות מחדש, והכפילויות נחתכות לפי מפתח מורכב — כלי, חתימת זמן, מספר עסקה.
מהירות שליפת ההיסטוריה. אחסון עמודתי ב-ClickHouse עם מחיצות לפי תאריך וכלי קורא רק את העמודות הנדרשות: נרות בכל טווח מחושבים על הדרך, בלי לעבור על אלפי קבצים. טווח היסטורי מוחזר תוך שניות, וחישוב מחדש של אסטרטגיות מפסיק להיות משימת לילה.
זמן שחזור ושלמות המרשם. הרפליקה עולה מהעתק של מחיצה, היממה האחרונה נמשכת מהיומן הכתיבה — חלון אי-הזמינות מצטמצם משעות לדקות. בכל מחיצה מתכנסים סכום ביקורת ומוני עסקאות: הפער נראה לפני שהנתונים יוצאים לצרכן, ולא אחרי חקירת תקלה.
במקום «עובד או לא עובד», בבדיקת הקבלה נמדדים שיעור הפערים המשוחזרים, זמן התגובה לטווח היסטורי וזמן העלאת הצומת. כך ארכיון המחירים מפסיק להיות מקור להפתעות.
אפשרויות ארגון ארכיון המחירים: השוואת מצבים
זרם העסקאות מגיע ברציפות, והשאילתות להיסטוריה אקראיות: לשחזר את מצב ספר ההזמנות ברגע נתון, לחשב מחדש אינדיקטור, להשוות ביצוע מול דוח הברוקר. מצב אחסון אחד לכל התרחישים בדרך כלל לא מחזיק מעמד: כתיבה מהירה באה על חשבון השליפות, וטבלאות אנליטיות נוחות מתקשות לקלוט אירועים בודדים. בהתחלה בוחרים בין שלוש סכמות, וכל אחת נשברת בפרופיל העומס שלה.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| אחסון עמודתי | שליפות אנליטיות לפי טווח זמן וכלי, חישוב מחדש של אגרגטים. דחיסה לפי עמודות יחד עם מחיצות לפי זמן נותנת חיסכון כפול בנפח על היסטוריה של שנים | הכנסות בודדות יקרות — נדרשת טעינה מקובצת. בלי פיצול לפי זמן, מחיקת נתונים ישנים הופכת לעבודה ידנית |
| יומן זרימה | קליטה בהשהיה מינימלית, שחזור מצב, עיבוד חוזר בחקירת תקלות. שומר אירועים לפי סדר הגעתם | שליפות עם סינון לפי שדות רבים דורשות הרכבה מחדש לאחסון נפרד. אחסון ארוך — רק עם דחיסת היסטוריה ורוטציה של מקטעים |
| סכמה היברידית | נדרשים גם קליטה בזמן אמת וגם אנליטיקה כבדה: היומן כותב את הזרימה, הטוען מעביר אותו למחיצות עמודתיות | יקר יותר לתחזוקה: השוואה, טעינה אידמפוטנטית ובקרת פיגור של הטוען |
הבחירה נקבעת על פי פרופיל העומס: היחס בין כתיבה לקריאה, עומק ההיסטוריה שנשמרת «חמה», ודרישות השחזור לאחר תקלה. עבור ארכיון מחירים שבו האנליטיקה דומיננטית, די באחסון עמודתי עם מחיצות לפי זמן; אם המערכת גם סוחרת, ההיבריד מכסה את שני התרחישים בלי לאבד אירועים.
שלבי ההטמעה: מביקורת הזרימה ועד מסירה לתפעול
זרימת הטיקים לא סולחת לפתרונות מקורבים: הכתיבות לא אחידות, השיאים גבוהים פי כמה מהממוצע, והמקור מעת לעת מחזיר כפילויות ונתונים בדיעבד. לכן אנחנו יוצאים לא מבחירת האחסון, אלא מסקר של קו הייצור הקיים — ורק אחר כך לסכמת הנתונים ולבדיקה על נפחים אמיתיים.
- ביקורת קו האחסון. אוספים מפה של המקורות: תדירות, פורמט, מקומות שבהם הולכות לאיבוד רשומות ונוצרות כפילויות. בפלט — דוח עם צווארי בקבוק ותחזית גידול הנפח.
- סכמת הנתונים. קובעים פיצול לפי זמן, מפתח מיון, רוחב שדות ודחיסה. מהחלטות האלה תלויים גם מהירות השליפה וגם הנפח התפוס: ב-ClickHouse השכבה החמה מחזירה היסטוריה לפי כלי ברמת דיוק של טיק, והישן עובר לארכיון הקר.
- הגדרת הקליטה והכתיבה. בונים פייפליין עם באפר בין המקור לאחסון: הוא מרסן שיאים, ואספקה חוזרת לא יוצרת כפילויות. בנפרד בודקים ניתוק קשר והפעלה מחדש של המקור.
- בדיקת עומס. משחזרים את הזרימה ההיסטורית בקצב מבצעי ומודדים את השהיית הכתיבה וזמן התגובה לשאילתות טיפוסיות. בודקים כשל צומת: השליפה לא אמורה להיפסק.
- השוואת נתונים. סכומי ביקורת לפי תקופות, השוואה מול המקור, שחזור מגיבוי עם מדידת זמן. פער במספר הרשומות מביאים לאפס.
- מסירה לתפעול. מוסרים קונפיגורציות, סכמת פריסה, מדיניות אחסון וניקוי, הנחיות לתורן ולוחות ניטור של הזרימה. פעולות שגרה צוות הלקוח מבצע בעצמו.
הרכב האספקה: קונפיגורציות, סכמות אחסון ותקנות
אנחנו מוסרים לא רק קו ייצור עובד, אלא כל מה שדרוש לתפעולו העצמאי. להלן — הסט המינימלי שנשאר אצל צוות הלקוח לאחר המסירה: בלעדיו, התקלה הראשונה בכתיבת הזרימה הופכת לפירוק הארכיון ביד.
- קונפיגורציות של שירותי הכתיבה והקריאה — פרמטרי באפר, גודל מנה, פסקי זמן לניסיונות חוזרים, מגבלות חיבורים מקבילים. הערכים מופרדים לשכבת הגדרות נפרדת: אפשר לשנות אותם בלי לבנות מחדש.
- תיאור סכמת האחסון — מפתחות וסדר מיון, פיצול לפי זמן, תוחלת חיים של מחיצות חמות וקרות, כללי דחיסה. הסכמה קשורה לפורמט הזרימה הנכנסת, ולכן בעת החלפת מקור רואים בדיוק מה לשכתב.
- תיעוד האחסון — מפת טבלאות ושדות שירות, ייעוד כל מחיצה, שאילתות טיפוסיות להשוואת נפחים ולאיתור פערים בנתונים.
- כללי גישה — תפקידים לשירותים ולבני אדם מופרדים: כתיבה, קריאה לפי קבוצת הכלים שלהם, גישה מלאה, פעולות ניהוליות. מתן הרשאות לא דורש עריכת קונפיגים בשרתים.
- תקנון תחזוקה — תדירות בדיקת השלמות, סדר דחיסת מחיצות, פעולות בפיגור כתיבה, ספי התראות ומי מגיב להן.
- סכמת הגיבוי — מה נגבה, באיזו תדירות, היכן נשמרים ההעתקים, כיצד נבדקת התאמתם וכמה זמן אורך השחזור על קו ייצור נקי.
- הנחיות לפעולות שגרה — הוספת כלי חדש לזרימה, חזרה למצב סכמה קודם, ייצוא חתך היסטורי לאנליטיקה.
הסט מעוצב כך שמהנדס חדש בצוות הלקוח פורש סטנד ומשחזר את התהליך לפי המסמך, בלי לפנות אלינו. אם המשימה קשורה למיגרציה או להרחבת הזרימה — תארו אותה, ונחזור עם הערכה ותוכנית עבודה.
מקרה בוחן: מרשם מחירים בלי פערים ועם שליפה מהירה
לפני: פערים בזרימה ודוחות של שעה
מחירים לארבעים כלים נכתבו לטבלה אחת על שרת אחד, וההכנסה בוצעה רשומה-רשומה. בשעות של תנודתיות גבוהה באפר הקליטה הצטבר מעל גדותיו, וחלק מהטיקים אבדו: ברבעון הצטברו פערים בשלושה כלים, ולא היה במה לשחזר אותם — הזרימה המקורית לא נשמרה בשום מקום.
בניית דוח לפי נרות שעתיים ומחיר משוקלל ארכה 40–60 דקות, כי האגרגט חושב בכל פעם על כל ההיסטוריה בבת אחת.
אחרי: ארכיון רציף ושליפה תוך שניות
את הארכיון פיצלנו לשתי שכבות: חמה — ב-DBMS אנליטית עמודתית עם מחיצות לפי יום וכלי, קרה — Parquet באחסון אובייקטים עם פיצול לפי תאריך וסימבול.
הקליטה נעשתה אידמפוטנטית לפי המפתח «כלי + חתימת זמן + מקור»: אספקה חוזרת לא יוצרת עוד כפילויות, ומעבר השוואה מול ארכיון הבורסה Deribit סוגר חורים ברשומות.
מה זז במדדים: אובדן טיקים — משבריר אחוז לאפס בחלון ההשוואה; דוח יומי — 40–60 דקות → 20–30 שניות; ייצוא מחדש של היסטוריה לשנה — כמעט יממה → 15–20 דקות; נפח הארכיון עם דחיסה עמודתית ודה-דופליקציה הצטמצם פי שישה תוך שמירה על העומק המלא.
במה נבדל ארכיון עמודתי מיומן זרימה?
ארכיון עמודתי ויומן זרימה הם שני סוגים שונים של אחסון, ובוחרים ביניהם לא לפי נפח הנתונים, אלא לפי מה שעושים איתם בהמשך.
הארכיון פורש את הטיק לפי עמודות — חתימת זמן, מחיר, נפח, צד העסקה — ודוחס כל אחת בנפרד: שליפה לפי טווח תאריכים ולפי מערכת שדות מצומצמת קוראת רק את העמודות הנדרשות ולא נוגעת בשאר.
היומן בנוי הפוך. הרשומות נרשמות בסוף הקובץ בדיוק לפי סדר הגעתן, האישור לא ממתין לאינדוקס, ולאחר תקלה המצב משוחזר בהרצה חוזרת עד למיקום המאושר האחרון. המחיר לכך — הקריאה: חתך של חודש מהיומן צריך להרכיב תוך מעבר על כולו.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| ארכיון עמודתי | אנליטיקה על ההיסטוריה: טווחי תאריכים, אגרגטים, מערכת שדות מצומצמת | הוספה בקטעים קטנים יקרה יותר — כל קטע דורש דחיסה; תיקונים נקודתיים איטיים |
| יומן זרימה | קליטת זרימת טיקים רציפה, שחזור לאחר תקלה, אספקת חלון «חם» | הנפח גדל באופן לינארי, חתך לתקופה ארוכה לא נבנה ממנו — נדרשת העברה לארכיון |
השחזור מפריד בין הגישות יותר מכל: היומן נותן נקודת שחזור לכל רשומה מאושרת, והארכיון — רק מקטעים ותמונות מצב שמפגרים אחרי הטיק האחרון.
בפועל מחזיקים את שניהם: היומן קולט את הזרימה ומשרת את הדקות האחרונות, והעברה ברקע דוחסת אותו למקטעים עמודתיים. הבחירה במערכת אחסון נתוני tick מצטמצמת לשלושה מספרים — עומק ההיסטוריה, השהיית הקריאה המותרת, ושיעור פעולות הכתיבה בפרופיל העומס הכולל.
ספקות טכניים: עונים על שאלות נפוצות
לפני תחילת הפיתוח של מערכת אחסון נתוני tick, מהנדסים בודקים ארבעה דברים: מה יקרה לרשומות בכשל צומת, כיצד גדל הארכיון, האם האנליטיקאים יקבלו נתונים גולמיים בלי ייצוא, והאם האחסון יסתדר עם קו הייצור הקיים. עונים לעניין.
מה יקרה לנתונים אם הצומת ייפול ברגע הכתיבה?
הזרימה נכתבת למקטעים בלתי ניתנים לשינוי: המקטע נרשם תחילה לדיסק ורק אחר כך נעשה גלוי לקוראים. מקטע לא שלם מזוהה לאחר הפעלה מחדש ומושלך, והחסר משוחזר בקליטה חוזרת. כפילויות במפגש נחתכות לפי המפתח «כלי + חתימת זמן», ולכן אספקה חוזרת לא מקלקלת את ההיסטוריה.
כמה מהר גדל הארכיון ומה מגביל אותו?
הנפח מחושב מראש — לפי מספר הכלים, תדירות העדכונים ועומק ההיסטוריה, ולכן ההרחבה מתוכננת לפני שנגמר המקום. החיסכון בא מדחיסה של שדות מאותו סוג ומהפרדה בין שכבה חמה לקרה: רשומות טריות על אמצעים מהירים, היסטוריה על זולים.
כיצד האנליטיקאים מקבלים גישה בלי להפריע לכתיבה?
הקריאה מופרדת לקו ייצור נפרד: השאילתות הולכות לרפליקות ולשכבת תצוגות, ולכן שליפה של חודש לא מעכבת את קליטת הנתונים. האנליטיקאי עובד דרך ממשק תואם SQL, בלי ייצוא ביניים לקבצים; ההרשאות מופרדות לפי כלים ולפי טווחי תאריכים.
האם נצטרך לבנות מחדש את קו הייצור הקיים?
אנחנו מתחברים לברוקרים הקיימים של ההודעות, למתזמן ולניטור, ומעבירים היסטוריה מהקבצים והטבלאות הנוכחיים עם בדיקת התאמה. אם חלק מקו הייצור נשאר על הסטאק הקודם, החלפת הנתונים נבנית כך שצרכנים פעילים ימשיכו לקרוא נתונים בלי לשכתב אותם.
נדבר על המשימה: מה נדרש מצדכם ומאיפה נתחיל
מדגימים על דוגמה: אצל לקוח ארכיון נתוני tick של Ethereum וזוגות ספוט שכן כמערך אחד, ולכן שאילתה על טווח צר סרקה את כל הנפח. דוח חודשי נאסף שעות, ואחרי תקלה היה צריך לשפוך את הנתונים מחדש.
פיצלנו את הזרימה למחיצות «תאריך + כלי», הפעלנו דחיסה עמודתית ואגרגטים מחושבים מראש — שליפת טווח נכנסת לשניות, נפח הארכיון הצטמצם פי כמה, ושחזור הצומת אורך דקות.
כדי לחזור עם הערכה ותוכנית עבודה, די לנו בסט מינימלי של נתוני פתיחה:
- רשימת הרשתות והכלים שעבורם נדרשים נתוני tick;
- עומק ההיסטוריה הנדרש ורמת הפירוט: עסקאות בודדות או אגרגטים לפי מרווחים;
- תרחישי קריאה — אנליטיקה, דוחות, ייצוא, שירותים פנימיים דרך API;
- פערים מותרים וכלל ההשוואה מול המקור;
- היכן מאחסנים: השרתים שלכם או ענן, אילו גישות נדרשות ואיזה תקנון חל על הנתונים;
- מגבלות לוחות זמנים ודרישות אחסון מצד הרגולציה.
בתגובה נשלח הערכה ותוכנית עבודה: סכמת מחיצות ומפתחות, סדר הטעינה הראשונית והכתיבה השוטפת של הזרימה, סדר המעבר מהאחסון הנוכחי בלי לעצור את האיסוף, וקריטריוני קבלה. תארו את המשימה — ונחזור עם הערכה ותוכנית.







