מה זה Multi-Tenancy בארכיטקטורת בקאנד¶
תארו לעצמכם שאתם בונים מערכת SaaS לניהול פרויקטים, ובתוך שנה יש לכם 500 חברות לקוחות שונות שמשתמשות בה. השאלה שכל צוות backend חייב לענות עליה בשלב מוקדם היא - האם כל חברה מקבלת מערכת נפרדת משלה, או שכולן חולקות את אותה מערכת בפועל, כשהנתונים שלהן פשוט מופרדים בצורה נכונה? זו בדיוק השאלה של Multi-Tenancy, ואיך שעונים עליה משפיע על הארכיטקטורה שלכם לשנים קדימה.
מה זה בעצם טננט¶
טננט (tenant) הוא בעצם לקוח נפרד של המערכת שלכם - לרוב חברה או ארגון שלם, עם המשתמשים, הנתונים וההגדרות שלו. במערכת Multi-Tenant, כל הטננטים האלה רצים על אותו קוד ואותה תשתית, אבל כל אחד מהם רואה רק את הנתונים שלו, כאילו יש לו מערכת פרטית משלו. הרעיון המרכזי הוא לבנות פעם אחת ולתחזק גרסה אחת של הקוד, במקום לנהל דיפלוי נפרד לכל לקוח.
מודל 1 - מסד נתונים נפרד לכל טננט¶
הגישה הכי "בטוחה" מבחינת בידוד היא לתת לכל טננט מסד נתונים נפרד לגמרי. אין שום סיכוי שנתונים של חברה אחת יזלגו בטעות לחברה אחרת, כי הם פשוט לא נמצאים באותו מקום פיזי. זה גם מקל על התאמות אישיות לטננט ספציפי, ועל עמידה בדרישות רגולציה מחמירות שדורשות בידוד נתונים מלא.
המחיר הוא תפעולי - עם 500 טננטים, יש לכם 500 מסדי נתונים לנטר, לגבות, ולעדכן כשעושים שינוי סכמה. שינוי פשוט בטבלה הופך למשימה שצריך להריץ 500 פעמים, וזה נטל תחזוקה שגדל ליניארית עם כל לקוח חדש.
מודל 2 - מסד נתונים משותף עם עמודת tenant_id¶
בקצה השני נמצא המודל הזול ביותר להפעלה - מסד נתונים אחד משותף לכל הטננטים, כשלכל טבלה יש עמודת tenant_id שמציינת למי שייכת כל שורה. כל שאילתה חייבת לסנן לפי tenant_id של המשתמש המחובר, כדי שהוא יראה רק את הנתונים שלו.
זה חוסך המון בעלויות תשתית ותחזוקה, כי יש רק מסד נתונים אחד לנהל. אבל זה דורש משמעת ברזל בקוד - אם מפתח שוכח תנאי tenant_id באחת השאילתות, ולו פעם אחת, זו לא באגה קטנה. זו דליפת נתונים בין חברות שונות, שיכולה להיות אסון תדמיתי ומשפטי של ממש. בגלל זה בפרויקטים כאלה נהוג להוסיף שכבת הגנה נוספת ברמת ה-ORM או המסד עצמו, ולא לסמוך רק על זיכרון של מפתח בודד.
מודל 3 - סכמה נפרדת לכל טננט¶
באמצע נמצא מודל של סכמה (schema) נפרדת לכל טננט, בתוך אותו מסד נתונים פיזי. כל טננט מקבל את הטבלאות שלו בנפרד, אבל כולם חיים על אותו שרת מסד נתונים. זה נותן בידוד טוב יותר ממודל ה-tenant_id המשותף, כי טעות בשאילתה לא יכולה לחצות סכמה בטעות כמו שהיא יכולה לחצות עמודה, אבל בלי לשלם את המחיר התפעולי המלא של מסד נתונים נפרד לגמרי.
הבעיה של המודל הזה היא שהוא לא תמיד סקיילבילי כמו שנדמה - עם אלפי טננטים, גם ניהול אלפי סכמות בתוך מסד אחד הופך למסובך, וכלים רבים למיגרציות פשוט לא בנויים לעבוד טוב בקנה מידה כזה.
הבעיה של השכן הרועש¶
כשכמה טננטים חולקים את אותם משאבים ממש, מגיעה בעיה שנקראת "noisy neighbor" - שכן רועש. טננט אחד שמריץ פתאום דוח כבד או מייבא כמות ענקית של נתונים, יכול להאט את המערכת עבור כל שאר הטננטים שחולקים איתו את אותו מסד נתונים או שרת, גם אם אין לו שום קשר אליהם. זו בדיוק הסיבה שחברות עם לקוחות ארגוניים גדולים מאוד לפעמים מוציאות אותם למסד נתונים נפרד, גם אם שאר הטננטים הקטנים יותר יושבים ביחד.
לסיכום¶
בסופו של דבר, Multi-Tenancy הוא לא בחירה טכנית בודדת אלא ספקטרום שלם, מבידוד מלא במסד נפרד ועד שיתוף מלא עם עמודת tenant_id, כששכבת הסכמה הנפרדת יושבת באמצע. אין תשובה אחת נכונה - הבחירה תלויה בכמה טננטים אתם מצפים להם, כמה כבד השימוש של כל אחד, ואיזו רמת בידוד הלקוחות שלכם דורשים. בקורס צד שרת עוברים על השיקולים האלה כשמדברים על תכנון מסדי נתונים למערכות אמיתיות, לא רק לפרויקט תרגול קטן.
אם אתם מתלבטים איזה מודל מתאים למערכת שאתם בונים, זה בדיוק סוג השיקול ששווה להתייעץ עליו לפני שכותבים שורת קוד אחת.