מערכות מבוזרות מודרניות הן כולן על פשרות. ביצועים, אמינות, מדרגיות ועקביות לא באים בחינם - אתה תמיד משלם מחיר איפשהו. כאן נכנס לתמונה משפט ה-CAP: זוהי נקודת המוצא להבנת הפשרות הבלתי נמנעות בתכנון מבוזר.
מדוע משפט CAP נכון? מה זה בעצם מסביר? והכי חשוב, האם זה מספיק? בפוסט זה, נחקור את משפט CAP, את מגבלותיו, את הביקורות שהוא התמודד, וכיצד רעיונות חדשים יותר כמו PACELC דוחפים את השיחה קדימה. בואו נצלול פנימה.
הגרסה הראשונה של משפט CAP התחילה כוויכוח בין ACID לעומת BASE . אבל עם הזמן, הוא התפתח, קיבל הוכחה רשמית, וסיים את לימודיו להיות משפט CAP כפי שאנו מכירים אותו היום.
משפט CAP קובע שמערכת מבוזרת יכולה לספק לכל היותר שניים מתוך שלושה מאפיינים בו זמנית :
מגבלה זו מאלצת מהנדסים לבצע פשרות קשות בהתאם למטרות המערכת ולמציאות של הסביבות המבוזרות שלהם.
עקביות ב-CAP אינה זהה לעקביות בעסקאות ACID . במשפט CAP זה מתייחס ללינאריזציה או עקביות חזקה . המשמעות היא שכל הצמתים במערכת מבוזרת חייבים תמיד להציג תצוגה אחת ועדכנית של הנתונים , ללא קשר לאיזה צומת מעבד את הבקשה. המשמעות היא שכל פעולת קריאה משקפת את הכתיבה העדכנית ביותר, לא משנה באיזה צומת אתה מבצע שאילתה.
💡 עקביות ב-ACID, לעומת זאת, מתמקדת בהבטחה שעסקה מביאה את מסד הנתונים ממצב חוקי אחד למצב חוקי אחר, בהתאם לכללים שהוגדרו על ידי סכימת מסד הנתונים. זה יותר על אכיפת אילוצי שלמות (כמו מפתחות זרים, אילוצים ייחודיים וכו') והבטחה שמסד הנתונים לא יישאר במצב לא חוקי, אפילו לנוכח קריסות.
זמינות ב-CAP פירושה שכל צומת שאינו כושל חייב להחזיר תגובה עבור כל בקשה שהוא מקבל, ללא קשר למחיצות הרשת . במילים אחרות, אם צומת בריא מקבל בקשה, עליו לעבד ולהגיב לה. עם זאת, CAP לא מבטיח שהתגובה תהיה תמיד "נכונה" או מעודכנת - היא רק מבטיחה שהצומת לא ייכשל בשקט (לדוגמה, במערכת AP צמתים עשויים להגיב עם נתונים מיושנים במהלך מחיצה כדי להבטיח זמינות ).
💡 אריק ברואר (המחבר המקורי של CAP) תיאר במקור את הנכס הזה בצורה קצת יותר גמישה כ: "כמעט כל השאילתות צריכות לקבל תגובה". עם זאת, בהוכחה הרשמית של CAP, הזמינות הוחמרה, ודרשה "כל שאילתה תקבל תגובה כל עוד הצומת המטפל בה תקין".
אולם בפועל, זמינות אינה ערובה מוחלטת - היא תלויה לעתים קרובות באילוצים ספציפיים למערכת, כמו כמה זמן אתה מוכן לחכות לתגובה. עבור מערכות בעולם האמיתי, זמן תגובה (או פסק זמן) ממלא תפקיד קריטי בעיצוב ה-SLA שלך (הסכם רמת שירות), למרות ש-CAP עצמו אינו מתייחס ישירות לזמן האחזור. עוד על זה בפוסט זה בבלוג .
סובלנות מחיצות היא כולה לשרוד כשלי רשת. אם צמתים אינם יכולים לתקשר עקב פיצול רשת (מחיצה), המערכת עדיין חייבת לעמוד בהבטחות העקביות או הזמינות שלה, בהתאם לבחירות העיצוב שלה. מחיצה מתרחשת כאשר צמתים אינם יכולים לתקשר עקב מנות שנפלו, פסקי זמן או פיצולי רשת.
מערכות מבוזרות אינן חיות בעולם אגדות עם רשתות מושלמות. מנות נושרות, פסקי זמן מתרחשים, ואינם נמנעים עליות חביון. בשל כך, סובלנות מחיצות אינה ניתנת למשא ומתן בכל מערכת מבוזרת - מחיצות יתרחשו במוקדם או במאוחר, כך שאינך יכול "לבחור" להתעלם ממנה, לא משנה כמה מפתה זה נשמע.
ב-CAP, סבילות למחיצות לא אומר שהמערכת ממשיכה לפעול כאילו כלום לא קרה. המשמעות היא שהמערכת צריכה להחליט אם לתעדף זמינות (AP) או עקביות (CP) במהלך מחיצה. אם היית מתעלם מסובלנות מחיצות, בעצם היית בונה מערכת מונוליטית לא מבוזרת.
הדרך הקלה ביותר להבין CAP היא לשקול מחיצת רשת - מצב שבו שני חלקים של מערכת מבוזרת אינם יכולים לתקשר זה עם זה. בתרחיש כזה, המערכת מתמודדת עם שלוש תוצאות אפשריות:
לפיכך, במהלך מחיצה , המערכת יכולה לספק רק שניים משלושת המאפיינים (C, A או P) . ברגע שהמחיצה נפתרה (כלומר, הצמתים מקיימים שוב אינטראקציה), המערכת יכולה להחזיר את כל שלושת המאפיינים, אך במהלך המחיצה עצמה , אי אפשר להימנע משינויים.
תוצאה של המשפט עבור מערכות אסינכרוניות היא שרק שלושה שילובים של עקביות, זמינות וסובלנות למחיצות אפשריים:
מערכות מסוג זה מגיבות לשאילתות, אך ייתכן שהנתונים המוחזרים לא תמיד מעודכנים, עם עדכונים איטיים יותר של הנתונים אך "תמיד" זמינים. דוגמאות למערכת כזו הן DNS, DynamoDB ו- Cassandra.
מערכות מסוג זה תמיד מחזירות נתונים עדכניים, אך ייתכן שחלק מהצמתים במערכת, או אפילו כולם, לא יגיבו אם הם מחולקים למחיצות. זה נותן עדכונים אטומיים אבל יכול להוביל לפסקי זמן. מסדי נתונים של NoSQL כגון Google BigTable, MongoDB, HBase ו-Redis הם כולן מערכות מסוג זה.
מערכות מסוג זה תמיד מחזירות נתונים עדכניים כאשר אין מחיצות. בגלל המגבלה האחרונה, בדרך כלל, מערכות כאלה משמשות רק בתוך מכונה אחת. דוגמאות לכך הן מסדי נתונים יחסיים קלאסיים.
במציאות, אנו בוחרים בין CP ל-AP כי CA הוא בעצם מונוליט ללא מחיצות. עבור מערכות בקנה מידה גדול, מעצבים לא יכולים לנטוש את P ולכן יש להם בחירה קשה בין C ל-A.
ב-CA, כשל בצומת פירושו חוסר זמינות מוחלטת של השירות. אבל זה לא משבית את המדרגיות, מכיוון שאנו יכולים לשכפל מונוליטים עצמאיים ולחלק את העומס עליהם
משפט CAP היה מושג בסיסי במערכות מבוזרות, אבל הוא לא חף ממגבלותיו. עם כל הבהירות שלו בהצגת הרעיון של פשרות, משפט ה-CAP זכה לא פעם לביקורת על כך שהוא מפשט מציאות מורכבת יתר על המידה, מה שהוביל לאי הבנות ויישום שגוי.
אחת הביקורות הנפוצות ביותר היא שההתלבטויות של משפט CAP - בחירה בין עקביות (C) לזמינות (A) - חלות רק כאשר מחיצת רשת (P) מתרחשת בפועל. בפעולה רגילה, כאשר הרשת יציבה ואין מחיצות קיימות, אין פשרה מובנית בין עקביות לזמינות.
יתר על כן, הפערים הללו אינם אוניברסליים בכל המערכת. בתוך אותה מערכת מבוזרת:
ניואנס זה הולך לאיבוד לעתים קרובות בדיונים ברמה גבוהה על CAP, מה שמוביל לסיווגים מופשטים מדי של מערכות כ"CP" או "AP" בכל רחבי הלוח.
ביקורת חשובה נוספת היא שמשפט ה-CAP אינו מסביר את החביון , למרות שהחביון והחלוקה קשורים באופן עמוק בפועל. לְדוּגמָה:
במערכות מבוזרות בעולם האמיתי, כאשר מתרחשת מחיצה או זמן השהייה גבוה, המערכת חייבת לקבל החלטה בתוך פרק זמן קצוב : לתעדף זמינות על ידי החזרת תוצאה אולי מיושנת, או לתת עדיפות לעקביות על ידי המתנה ארוכה יותר (ועלולה לא להגיב). ההשקפה הבינארית של CAP אינה תופסת את המורכבות של החלטות אלו.
משפט CAP מציג עקביות, זמינות וסובלנות מחיצות כמאפיינים בינארים - או שיש לך אותם או שאין לך. אבל בפועל, כל שלושת המאפיינים קיימים על ספקטרום :
אופי רציף זה של המאפיינים הופך את CAP לפשטני מדי עבור מודלים של המורכבות של מערכות מבוזרות מודרניות.
בעוד ש-CAP חולל מהפכה בהבנתנו לגבי פשרות במערכות מבוזרות, זו לא המילה האחרונה בנושא. משפט PACELC שתואר על ידי דניאל ג'יי עבאדי נחשב לגישה חלופית לתכנון של מערכות מבוזרות. הוא מבוסס על מודל CAP, אך בנוסף לעקביות, זמינות וסובלנות למחיצות הוא כולל גם חביון והדרה לוגית בין שילובים של מושגים אלו.
PACELC מציגה שני מצבי פעולה נפרדים עבור מערכות מבוזרות:
בעוד שמחיצות הן בלתי נמנעות במערכות מבוזרות, הן נדירות בהשוואה לאתגרים המתעוררים במהלך פעולה רגילה. במערכות מבוזרות מודרניות, חביון הוא לעתים קרובות צוואר בקבוק גדול יותר ממחיצות רשת, במיוחד עבור יישומים בקנה מידה עולמי. זה המקום שבו PACELC מתמקדת - על ידי התייחסות לשינויים המתרחשים כאשר המערכת פועלת ללא מחיצות. בניגוד ל-CAP, המתמקדת אך ורק בהתנהגות במהלך תרחישי כשל, PACELC מדגישה את ההחלטות שעל האדריכלים לקבל מדי יום כדי לאזן את ההשהיה (L) והעקביות (C) :
על ידי הרחבת השיחה מעבר למחיצות כך שתכלול פעולה רגילה, PACELC מבטיחה שהביצועים היומיומיים של מערכות מבוזרות יטופלו בחשיבות הראויה.
ניסוח משפט ה-CAP היה אירוע משמעותי בקהילה, ומחקרים על השפעתו על תכנון מערכות מבוזרות הראו שמתכננים של מערכות מבוזרות לא צריכים להגביל את המערכת לשני מאפיינים - עליהם לשאוף למקסם את הערבויות הנדרשות בכל אחת מהן. מקרה מסוים. לצורך כך, סביר לחלק את המערכת למקטעים שלכל אחד מהם דרישות משלו ולתכנן את המערכת בהתאם לדרישות של כל אחד מהמקטעים.
משפט ה-CAP היה אבן יסוד בחשיבת מערכות מבוזרות במשך עשרות שנים. זה נתן לנו מסגרת להנמקה לגבי הפערים המובנים של עקביות, זמינות וסובלנות לחלוקה. אבל במובנים רבים, זה פישוט של המציאות, בהנחה של בחירות בינאריות והתעלמות מגורמים קריטיים כמו חביון.
PACELC מתבססת על CAP, ומכירה בכך:
גם CAP וגם PACELC הם כלים יקרי ערך, אבל גם לא מתכון שלב אחר שלב לבניית מערכות. במקום זאת, הם מספקים מודלים מנטליים להערכת פשרות והבנת הגבולות של ארכיטקטורות מבוזרות.
תודה שקראת!
סקרן לגבי משהו או יש לך מחשבות לשתף? השאר את תגובתך למטה! בדוק את הבלוג שלי או עקוב אחריי דרך LinkedIn , Substack או Telegram .