ליאור בר-און לפני 3 שנים כ- 13 דקות קריאה
ארכיטקטורת-נתונים במערכות מוצר
יש המון שיח על ארכיטקטורות נתונים בשנים האחרונות. Data Lakes, Lambda Architecture ו Delta Lake וכו'.
כמי שעובד במערכת מוצר (מיד אגדיר) – רוב הדיונים הללו עוברים מעל הראש:
- כמות הנתונים שמתעסקים איתה היא לא כ"כ גדולה – ובטח לא עצומה.
- למשל: בסיס נתונים המכיל "רק" 2TB של נתונים – ועוד כמה events או מסמכים התופסים יותר מקום – אך מאוכסנים ב S3 (שירות אכסון הנתונים של אמזון, בעל ממשק דומה למערכת קבצים).
- את רוב העבודה יכולים, וגם רוצים – לעשות בבסיס הנתונים רלציוני.
- אולי חלק מהמידע הוא Document-Based (הרי PostgreSQL ו MySQL תומכים בניהול מסמכי JSON) אולי יש עוד בסיס נתונים אחד או שניים NoSQL – אך הם משתמשים לתהליכים מאוד ספציפיים.
- אין עיבודי מידע גדולים / מורכבים בלב המערכת – שבסיס נתונים רלציוני לא יכול להם.
- אולי יש כמה תהליכי אצווה שמעבדים הרבה נתונים – ואז סיכומים שלהם הופכים לדוחות או חוזרים כסיכום למערכת – אך לא באופן שישנה את הארכיטקטורה הבסיסית של המערכת.
- המערכת היא אחידה, ולא מורכבת מתתי מערכות שונות ומשונות (למשל: שנבעו מסדרה של רכישות).
יש לנו Lambda Architecture וגם Data Warehouse וגם Data Lake (ועוד אחרים) – אך בעיות הדאטה הגדולות שלנו לא נמצאות שם.
אני רוצה להקדיש פוסט לבעיות-נתונים שאינן מסביב ל Streaming, High Scale, או Realtime. יש המון חומר על התמודדות עם הבעיות (הגדולות, המכובדות) הללו – אך יש עוד כמה בעיות, קשות, שלא זוכות לאותה רמה של דיון.
מה הן "מערכות-מוצר", ומה בעיות הנתונים הנפוצות שלהן?
מערכת-מוצר היא מערכת שמשרתת לקוחות קצה (אנשים פרטים, עסקים קטנים או גדולים – אך מערכות אחרות) ורוב האתגר בה הוא ניהול המידע וה Flow העסקיים. למשל: LinkedIn, Moday, Gett, Next-Insurance, ועוד רבים.
אני חושב שהשם "מערכת-מוצר" מתקשר במידה רבה להיותה של המערכת – מערכת הליבה של חברות-מוצר, שההצעה העסקית שלהן היא מסביב למוצר מסוים. שירות החברה הופך את מערכות הללו להיות קריטיות ושלא חוסכים עליהן במשאבים. זה שונה מאוד ממערכת-מידע בעל משמעות קטנה לארגון (נניח: מערכת דיווח שעות לעובדים, אלא אם זה המוצר של החברה).
כמובן שהגבול הזה הוא אפור ומטושטש: סטארט-אפ קטן עשוי להיות תלוי עסקית לחלוטין במערכת-מידע פשוטה למדי, בעוד נטפליקס יוצרת מערכת למתרגמים מורכבת וסבוכה פי כמה, בעוד זו אינה מערכת שמהווה יתרון תחרותי לארגון.
"מערכת מוצר" הוא בקיצור ביטוי שבא לבדל מול מונחי-עבר כגון "מערכות-מידע" או "Enterprise System", שמתקשרים לרבים למערכות צדדיות ושאינן מעניינות כ"כ מבחינה טכנולוגית ו/או הנדסית.
בואו נראה כמה תכונות של מערכת-מוצר שכזו, והאתגרים שנובעים מהן בעולמות הדאטה. אני אתייחס כרגע ספציפית למערכת של Next-Insurance, אך היא לא שונה מהותית ממערכות אחרות בקטגוריה:
- המערכת משתמשת בכאלף טבלאות בבסיס-הנתונים (יש גם טבלאות טכניות. 500-700 בעלות נתונים עסקיים בעלי-משמעות). זה בערך 10 טבלאות לכל מפתח – מדד שיכול להצביע על העומק / מורכבות של המודל העסקי המטופל.
- אציין שיש כ 30 מיני-שירותים, ואני סופר את הטבלאות של כולם ביחד.
- שינויי סכמה בטבלאות קיימות מתרחשים כל שבוע. כלומר – המודל דינאמי למדי.
-
- עבודה ב Continous Deployment הופך את הבעיה לקשה יותר: כל שינוי – מוחל מיד על הנתונים הקיימים וישפיע על כל צרכני-הנתונים.
-
- ישנם כ 20 אנליסטים (והמספר גדל) שאמורים להתמודד עם כל המגוון הזה של הנתונים – ולהסיק ממנו מסקנות מדויקות, וחד משמעיות – מסקנות שיובילו להחלטות עסקיות, למשל: מה ההשפעה של שינוי מסוים במערכת.
- דיוק הנתונים עשוי להיות בעל חשיבות עליונה: טעות של 1 למיליון בנתונים כספיים או בנתונים לגבי כיסויים ביטוחיים – היא כבר בעיה שיש לטפל בה (בשונה ממערכות עיבוד נתונים רבות, המוכנות לספוג איבוד/אי-דיוק נתונים גדול בהרבה. לדוגמה מערכת שאיבוד / טעות בעד 0.02% מהנתונים, 1 ל 5,000 – לא נחשב בעיה)
- כמובן שגם במערכות מוצר יש מידע חשוב יותר וחשוב פחות – ויש סובלנות לאיבוד/אי-דיוק מידע באזורים מסוימים.
- טווח העבודה העיקרי עם הנתונים הוא שנה עסקית, כלומר 12 חודשים לאחור. אם היה באג בנתונים מלפני 3 חודשים – חשוב לחזור ולתקן אותם, ואת כל ההשפעות שנבעו מהשינוי => מה שאולי גורר עוד ועוד תיקוני נתונים, ברקורסיה.
אם לא "קפצו" לכם, עד כה, כמה בעיות שנובעות ממודל שכזה, אציין אותם במפורש:
- תהליך ה ETL (העברת הנתונים בסיס הנתונים של המערכת למשטח עבודת-נתונים "נוח יותר" כמו Data Lake או Data Warehouse) – צריך להתמודד עם שינויים יומיומיים בסכמה.
- עם שינויים כגון הוספת טבלה חדשה – קל להתמודד. זו יכולת מובנה ברוב כלי ה ETL.
- שינויים כגון שינוי סכמה או תיקון היסטורי של נתונים (Backfill) – כבר דורשים טיפול מיוחד, במיוחד כדי לא להוציא את הנתונים ב"משטחי העבודה של הנתונים" מעקביות (Consistency).
- תקשור מודל הנתונים: כיצד אנליסט אמור להתמודד עם מגוון של מאות טבלאות שמתווספות ומשתנות כל הזמן?
- מה הסיכוי לחוסר הבנה לגבי משמעות הנתונים, שיגררו ניתוח לא מדויק או אפילו שגוי לגמרי? (רמז – לא קטן בכלל)
- כאשר ה Data Engineers (האחראים על תהליך ה ETL) והאנליסטים "סובלים" – ההשפעה מחלחלת בחזרה גם למהנדסים.
- "לחץ" להאטה בקצב / עומק השינויים. כאשר דוחות / ניתוחים מורכבים מתבססים על מבנה נתונים מסוים – שינוי המבנה עשוי לגרור עבודת עדכון של שבועות ואף חודשים. הברירה השנייה: להורות למפתחים לא לשנות את מבנה הנתונים "ולהסתדר" עם מבנה הנתונים הקיים (מה שעשוי ליצור בעיה גדולה למפתחים).
- דיונים ושאילתות חוזרות על משמעות הנתונים – מה שגורר זמן עבודה משמעותי בין מפתחים ואנשי-נתונים לגבי משמעות הנתונים.
- תסריט שמי שחי בעולמות הללו בטח מכיר: מדד עסקי מראה ירידה בדוחות, ועכשיו צריך לחקור: האם הבעיה בדוחות, בשינויי מודל הנתונים, או באג בקוד? המנכ"ל או מי מטעמו מגיע למפתחים בבקשה "להוכיח שזה לא באג בקוד"…
- כל זה גורר לאיבוד אמון בין הקבוצות, מה שרק שעלול לגרום להגביר את הבעיות, ואז שוב לפגוע באמון – וחוזר חלילה. מחזור של הסלמה…
- ככל שהמודל העסקי מורכב ומגוון – כך קשה גם יותר למפתחים להבין אותו, ולשמור עליו עקבי בלי שיצוצו "כפילויות" או "סתירות" במודל בין המפתחים, שיחזרו ויסבכו את על העניין.
- כיצד מנתחים נתונים היסטוריים? החברה קיימת 10 שנים, ומודל הנתונים בה משתנה תדיר. איך מנתחים מגמות לאורך השונים על מודלים משתנים.
- גישה אפשרית אחת: כל פעם שמשנים מודל עסקי – עושים migration של כל מידע העבר למודל המעודכן.
- תהליך migration הוא תהליך קשה ויקר (בשעות עבודה). נדרשים לא פעם "להשלים/להמציא" נתונים שלא היו בעבר – מה שמקטין את האמינות של הנתונים לאורך זמן.
- גישה אפשרית אחרת: הניתוחים העסקיים יידרשו להכיר את כל הווריאציות של המודלים העסקיים לדורותיהם – מה שיהפוך אותם למורכבים הרבה יותר לביצוע.
- גישה אפשרית אחת: כל פעם שמשנים מודל עסקי – עושים migration של כל מידע העבר למודל המעודכן.

אז איך מתמודדים עם בעיות הנתונים של מערכות-מוצר?
לצערי, חיפשתי רפרנסים – ולא מצאתי מתודולוגיות סדורות לעניין הזה. נראה שכמה חברות מציעות כלים-תומכים כאלו ואחרים (תיעוד נתונים, ETL טוב וגמיש יותר, וכו') – אך כלים אינם מתודולוגיה.
הנה המתודולוגיות העיקריות שאני מכיר:
הברירה הטבעית
אנו מאמינים בעובדים שלנו, יש לנו ערך של "עבודת-צוות" בחברה, ולכן – המפתחים, האנליסטים, אנשי הנתונים וכו' – יסתדרו. גם בינם ובין עצמם וגם בין הקבוצות.
כלומר: לא נשליט מתודולוגיה עקרונית – אלא נסמוך על היכולות והרצון הטוב של העובדים השונים, שיסתדרו.
על זה נאמר: לארגון יש מדיניות חוץ – אך אין לו מדיניות פנים.
Long Release Cycle
במערכות של חברת SAP (חברת ERP – מערכות המידע המורכבות אולי בעולם) יש מודלים עסקיים אדירים ומורכבים. היה ספר של הטיפוסים במודל – שרק הוא הגיע לאלפי עמודים, ולא ניתן היה יותר להדפיס אותו בכרך אחד. גם שם היו הרבה מפתחים (כ 18K, בזמני) – אבל הבעיות הנ"ל לא היו בעיות גדולות. מדוע?
- היה כלל שלא משנים Schema של בסיס נתונים בגרסה שאינה major.
- גרסת major יצאה אחת לכמה שנים.
מפתחים יכלו לשנות סכמה כל שבוע, אך הצרכנים של הנתונים – היו רואים את השינוי בפעם בכמה שנים (במקרה הטוב, רוב הלקוחות מעדכנים גרסה אחת לכמה גרסאות), וכל שינוי היה מתועד למשעי (במערכות העסקיות של החברה, לא בתשתיות).
זה מצב לא-רלוונטי לסטארט-אפים, בטח SaaS. אפשר לדלג.
Event Log / Event Streaming
המודל המקובל ביותר, By Far, בעניינים של שיתוף נתונים בין המערכת האופרטיבית (מפתחים) – למערכות הנתונים (אנשי-דאטה מסוגים שונים) הוא על בסיס Events:
"אירוע: משתמש חדש נרשם במערכת… הנה כל הפרטים"
"אירוע: משתמש שינה את תמונת הפרופיל שלו…. הנה כל הפרטים"
"אירוע: משתמש על Accept לאחר 5 שניות מרגע שהופיע המסך… הנה כל הפרטים".
בואו נעשה כמה הבחנות:
- אירוע מתאר משהו שהתרחש – ולא את מצב קיים.
- כדי לדעת את המצב הקיים – יש להרכיב את כל רצף האירועים על אובייקט רלוונטי.
- אירוע הוא encapsulated – קרי מכיל את כל המידע הרלוונטי. בניגוד לטבלאות בהן עלי אולי לעשות פעולת JOIN לעוד כמה טבלאות להשלים את התמונה, האירוע מכיל את כל הנתונים הרלוונטיים.
- זה כמובן אידאל, אף אחד לא מונע מאתנו לשלוח events חלקיים.
- צרכנים שונים, עשויים להזדקק לאירועים שונים בתכלית. כנראה שנרצה להכליל כמה שיותר צרכנים באירוע – אבל זה לא תמיד יצליח.
- אירוע הוא contract ("חוזה") – השולח והמקבל חייבים להסכים על תוכן האירוע ומשמעותו, אחרת המודל לא יוכל לעבוד.
- מה השדות ומה משמעותם. אלו שדות מופיעים באלו מקרים.
- מתי נשלח אירוע, ומתי לא. למשל: משתמש עדכן תמונת פרופיל לאותה תמונה בדיוק. האם זה אירוע, או לא?
- האירועים הם מסביב להתרחשות עסקית – ולא מסביב להתרחשות טכנית. ההבחנה ב"עסקיות" של אירועים כמובן תלויה בין חברה לחברה.
- שלב הלוגין של משתמש במערכת כולל אולי עשרות צעדים טכניים, אבל מבחינה עסקית – מעניין רק הלוגין כאירוע אחד.
- כמו שציינתי, זה אידאל, ואף אחד לא ימנע מאתנו לשלוח אירועים ברזולוציה שאינה עסקית באמת.
- אירוע קנייה של מוצר הוא אירוע יחיד ללקוח, אבל כנראה מספר אירועים ברמה העסקית לחברה. צפייה במוצר, דפדוף במוצרים דומים, בדיקת פרטי המשלוח, ושלבי הקנייה.
- כמו שציינתי, לארגונים שונים רזולוציה שונה היא "עסקית". עבור גוגל (מנוע חיפוש) הצגה של תוצאה בדף החיפוש עשויה להיות "אירוע עסקי" ובוודאי כל הקלקה על קישור.
- שלב הלוגין של משתמש במערכת כולל אולי עשרות צעדים טכניים, אבל מבחינה עסקית – מעניין רק הלוגין כאירוע אחד.
ה Events לרוב מיוצרים בקוד של המערכת האופרטיבית (מיקרו-שירותים) ועוברים על גבי Event Streaming Infrasturcture (כגון Kafka, Pulsar, Kinesis) ל Data Lake. משם הם יעברו ל DWH (או Data Lake אחר) שם "יסכמו את האירועים" לצורה של אובייקטים המציגים את המצב הקיים, או שיעשו עליהם ניתוחים ברמת ה Events.
הגדרת Events היא הזדמנות להגדיר חוזה ברור, לנתק את ה coupling בין המבנה הפנימי של בסיס-הנתונים למודל העסקי שאותו צורכים צרכני-הנתונים (ואז אין בעיה לשנות Schema כל יום – כל עוד מבנה האירועים נשמר), ובכלל לעבוד עם נתונים ברמת הפשטה גבוהה יותר ("אירועים עסקיים" ולא "שורות שנשמרות בבסיס הנתונים").
בכל זאת, אף אחד לא מבטיח לנו שהפוטנציאל ימומש בחלקו או במלואו – מימוש טוב ויסודי (Data Dictionary, Data Modeling, ומערכות נתונים מתאימות) הם קשים ליישום, והכרחיים להצלחה.
ישנן עוד כמה בעיות מובנות במודל ה Events:
- בסיס נתונים הוא אמין יותר מ Event Stream Infra: הודעות עלולות להיאבד או להישלח פעמיים + Events הם עיבוד הנתונים – ולא מקור הנתונים. לכאורה יש כאן ירידה מ"מערכות נתונים שצופות ישר בבסיס הנתונים, the source of truth".
- לכל אלו שקופצים עם "Kafka supports Exactly-once message delivery semantics" אני אזכיר שתקלות יכולות להתרחש גם לפני / אחרי Kafka.
- בסופו של דבר, יהיה לנו כנראה תהליך Scheduled של Eventual Consistency – שיאתר פערים במידע, וישלים אותם.
- תיקוני נתונים הם קשים הרבה יותר ב Events (יחסית לבסיס נתונים). נניח גילינו שחייבנו 15K לקוחות ביותר מדי – נרצה לחזור ולעדכן אותם. שתי הגישות העיקריות לתיקון נתונים הם:
- הוספת אירוע מתקן (או סדרה של אירועים מתקנים), עם Effective Date של עבר – כך שמי שמרכיב את האירועים ידע להרכיב אותם נכון.
- קושי עיקרי כאן הוא לייצר Delta "נכונה". כלל שהלוגיקה העסקית מורכבת יותר, והאירוע הוא ברמת-הפשטה גבוהה יותר, יהיה קשה לייצר את ה Delta נכון – ולוודא שהיא נכונה. קוד המערכת כתוב בכדי לייצור אירועים חדשים, ויצירת של Deltas (נכונות) – עשוי להיות אתגר ממשי.
- לכל אירוע מוצמד מזהה חזק (GUID), ואירועים יישלחו מחדש – מתוקנים.
- כאן הקושי הוא לאתר אלו אירועים יש לתקן (אירוע הוא הפשטה מעל מספר טבלאות בסיס נתונים + הם יושבים ב Data Lake – מערכת נוספת שמפתחים צריכים "להתעסק" איתה). גם כאן, כשאין Delta, צריך לדעת איזה רכיב בדיוק במערכת הקוד יש להפעיל – רכיב שאולי לא נבדק במוד הרצה שכזה – וזה אתגר. (רמז: מתחילים בכתיבת Tests לתסריט החדש הזה).
- תיקון נתונים מתחיל כתהליך, "One-off", ידני – אך מהר מאוד מגלים שזו שגרה, ומשקיעים בתהליכים מסודרים ואוטומטיים לתקן מידע לאחור.
- הוספת אירוע מתקן (או סדרה של אירועים מתקנים), עם Effective Date של עבר – כך שמי שמרכיב את האירועים ידע להרכיב אותם נכון.
- הגדרה של תיאור/Contract ברור וחד-משמעי של כל Event הוא לא תמיד דבר פשוט, בטח כשיש עשרות ומאות אירועים במערכת.
- כתיבת בדיקות אוטומטית שיאשרו שלא חורגים מהחוזה שהוסכם לכל אירוע.
מודל ה Events הוא Step Up משמעותי בהשקעה ה Up-front הנדרשת, ולכן ארגונים נוטים לדחות את המעבר – ולהסתמך על "הברירה הטבעית" (בה יותר קשה למדוד את גודל הנזקים שנגרמים) רק עוד קצת.

Well-monitored Data Sharing
במקרים מסוימים, ולרוב רק לחלק קטן מהמידע – מחליטים להמשיך ולשתף את מבנה (סכמה) הנתונים הפנימי של המערכת עם מערכות / לקוחות ה Data של המערכת האופרטיבית. במקום להסתמך על "מזל" (להלן גישת "הברירה הטבעית") – מנטרים ומנהלים היטב את שיתוף הנתונים:
- הנתונים, והמשמעות מדויקת שלהם מתועדים ומוגדרים-היטב.
- כל שינוי בסכמת נתונים מתוכנן ומתוקשר מבעוד מועד, לכל הצרכנים – על מנת שיתכוננו.
- אולי הם שותפים שווים למבנה הנתונים, וכל שינוי הוא דיון – ולא "תקשור".
- מתעדפים שינויים בקוד – על פני שינוי סכמת הנתונים. למשל:
- אם מפתחים יכולים להתאמץ קצת יותר כדי לא לשנות את סכמת הנתונים – שיעשו זאת.
- כאשר עוברים למודל חדש – נעשה migration לכל הנתונים ההיסטוריים להתאים למודל המעודכן.
הסיבות העיקריות למודל ה Well-monitored data sharing הוא לרוב:
- נתונים שלא נוטים להשתנות בצורה תכופה.
- נתונים שרמת ההפשטה הטבעית שלהם (Raw Data) – תואמת לרמת ההפשטה הרצויה מבחינת העניין העסקי.
- נתונים מאוד קריטיים ורגישים לארגון, בהם רוצים להסתכל על ה Source of Truth עם מינימום תרגומים / תחנות בדרך.
דוגמה קלאסית לכאלו נתונים הן נתוני-תשלום (כרטיס אשראי, העברות בנקאיות, וכו'):
- מבנה הנתונים לרוב נגזר ממערכות סליקה / תקנים בינלאומיים – שכמעט ולא משתנים.
- כל נתוני התשלום כמעט (אולי חוץ מ ids פנימיים) – עשויים להיות מעניינים לצרכני-הנתונים בארגון.
- הארגון מעוניין לדעת על כל תשלום שהיה / נכשל / התבטל, בלי לפספס אף שורה.
דוגמאות נוספות עשויות להיות (נניח: בחברת ביטוח) – רישום הכיסויים הכלולים בכל פוליסה, רשימת התשובות שענה כל משתמש בהגשת הבקשה לפוליסה. אלו דוגמאות לנתונים קריטיים לארגון ושאין טעם להוסיף בהם רמת הפשטה. ככל שהתכונות הללו מתרבות סביר יותר שנרצה להעביר את הנתונים ההלו כפי שהם (נניח: Sanpshot יומי) ופחות להעביר אותם כאירועים.
סיכום
ניסיתי בפוסט לתאר בעיות-נתונים של מערכות-מוצר, מערכות מידע מורכבות – שיש לנו את הזמן והמשאבים "לעשות בהן מה שנדרש".
שני המודלים הרלוונטיים הם כנראה ה Event-Steaming ו Well-monitored shared Data. אפשר לעשות בהם mix and match ע"פ הצרכים של כל ארגון / מערכת.
התנסיתי ואני מתנסה עדיין במודלים הללו במצבים שונים – ועדיין צצות שאלות ודילמות מדי פעם. אני מקווה שהתמונה הזו מספיקה – בכדי לשרת אחרים.
כמו כן, אשמח לתובנות שיתופים על חוויות ופתרונות בנושאים הללו.
תודה לנדב נוה, ששימש כ Reviwer לפוסט – ועזר לי לדבר יותר לעניין.
לינקים רלוונטיים:
The Log: What every software engineer should know about real-time data's unifying abstraction – מאמר של יוצר Kafka מ 2013, שגם עוסק במבנה הטכני של Event Streams – אבל גם בכל בעיות הדאטה שציינו כאן (LinkedIn היא חברת-מוצר / מערכת-מוצר קלאסית)