למה Distributed Systems שוברים את האינטואיציה שלך
ב-1987 כתב Leslie Lamport: 'A distributed system is one in which the failure of a computer you didn't even know existed can render your own computer unusable.' זה לא פואטיקה, זו מציאות יומיומית. כשMonday.com משרתת 200,000 חברות, כשGong מסנכרנת calls בזמן אמת בין ישראל לניו יורק, כשFiverr מאשרת תשלום בין פרילנסר בתל אביב ולקוח בטוקיו, כולן מתמודדות עם אתגר אחד: איך לגרום לעשרות שרתים לפעול כאחד, כאשר הרשת ביניהם לא אמינה, השעונים לא מסונכרנים, ושרת אחד עלול לקרוס בלי התראה.
בשיעור הזה Claude הוא המורה, הארכיטקט, ומחולל הדוגמאות. תלמד לא רק תיאוריה, אלא איך להשתמש ב-Claude כדי לנתח מערכות אמיתיות, להכין ריאיונות system design, ולהבין למה databases מפורסמות שיקרו בתיעוד שלהן.
CAP Theorem, ה-Trade-off שאי אפשר לברוח ממנו
Eric Brewer הציג את CAP theorem בשנת 2000: distributed system יכולה לספק לכל היותר שניים מתוך שלושה, Consistency, Availability, ו-Partition Tolerance. בפועל, network partitions בלתי נמנעות. הבחירה האמיתית היא בין CP ו-AP.
| סוג | מה קורה בpartition? | דוגמאות | מתי מתאים? |
|---|---|---|---|
| CP | מסרב לשרת requests כדי לשמור על consistency | etcd, Zookeeper, HBase | Financial ledgers, config management, leader election |
| AP | ממשיך לשרת אבל users שונים עשויים לראות data שונה | Cassandra, DynamoDB, CouchDB | Shopping carts, news feeds, user sessions |
Kubernetes משתמש ב-etcd עם CP, מוכן ל-downtime קצר כדי שכל ה-nodes יראו את אותו cluster state. Amazon בחרה AP לshopping cart שלה: cart שתמיד עובד שווה יותר מconsistency מושלמת שגורמת לו לפרוח. הבחירה היא תמיד product decision, לא רק technical.
PACELC, למה CAP לבד כבר לא מספיק
Daniel Abadi הציג ב-2010 את PACELC, שמרחיב את CAP: גם בהיעדר partition, מערכת חייבת לבחור בין Latency ל-Consistency. הנוסחה: אם Partition, בחר A או C. אחרת (Else), בחר L או C.
למה זה חשוב? כי partitions הן נדירות. ב-99.9% מהשניות המערכת עובדת נורמלית, ועדיין חייבת לבחור: האם כל read מחזיר data עדכני (consistency, latency גבוה), או data קצת ישן אבל מהיר (low latency, eventual consistency)?
- EL, מעדיפים מהירות: Cassandra, DynamoDB, קוראים מreplica קרובה גם אם לא הכי עדכנית. מתאים לfeed חברתי, המלצות.
- EC, מעדיפים דיוק: Spanner, CockroachDB, כל read מחייב quorum. איטי יותר, אבל תמיד עדכני. מתאים לmoney transfers.
ריאיונות system design ב-2025 מצפים שתזכיר PACELC, לא רק CAP. זה ההבדל בין מועמד שלמד תיאוריה למועמד שהבין את ה-trade-offs האמיתיים.
Raft Consensus, איך 5 שרתים מסכימים תחת לחץ
בעולם שבו servers נופלים ומסרים הולכים לאיבוד, איך מבטיחים שכל הcluster מסכים על מי ה-leader ומה הstate? זו בדיוק הבעיה שRaft פותר. Kubernetes משתמש ב-etcd שבנוי על Raft. CockroachDB, TiDB, גם.
- Leader Election: כל follower מחכה timeout אקראי. אם לא שמע מleader, מציג עצמו כcandidate, מבקש votes. מי שקיבל majority, נבחר leader. Randomization מונעת שניים ינסו בו-זמנית.
- Log Replication: leader מקבל write, מוסיף לlog שלו, שולח לכל followers. רק אחרי שmajority אישרו, commit. אם leader נופל לפני commit, entry נשכח. אם אחרי, entry ישוחזר מהfollowers.
- Split-Brain Prevention: leader חייב לשמור majority בכל commit. בcluster של 5 nodes, 3 נדרשים. אם רק 2 זמינים, מסרבים לכתוב. זה מונע שני leaders שמקבלים writes סותרים.
עם 5 etcd nodes, אם 2 נופלים, החלטות scheduling חדשות מוקפאות, אבל pods שרצים ממשיכים לרוץ. etcd מעדיף CP: לא לשרת עדיף על שרת data שאינו עדכני.
Distributed Transactions, הבעיה שאין לה פתרון מושלם
בmonolith, transaction פשוטה: BEGIN, queries, COMMIT. ב-microservices, transaction עלולה לגעת בשלושה services שונים עם databases שונים, ואי אפשר לעשות global rollback.
Two-Phase Commit (2PC): Phase 1, coordinator שואל את כולם 'אתה מוכן?'. Phase 2, אם כולם אמרו yes, שולח commit. הבעיה: אם coordinator נופל בין Phase 1 ל-Phase 2, participants נשארים locked לנצח. זה blocking nature של 2PC, anti-pattern ב-microservices.
Saga Pattern: sequence של local transactions. לכל step יש compensating transaction (undo). booking טיסה הצליח אבל booking מלון נכשל? מפעילים compensating transaction שמבטל את הטיסה. אין global lock, אבל ה-system יכול להיות ב-inconsistent state זמנית, צריך לתכנן את ה-UX בהתאם.
שלוש הטעויות הנפוצות ביותר
- 'הרשת אמינה': Peter Deutsch ניסח את 8 Fallacies of Distributed Computing. הראשונה: 'The network is reliable.' זו הנחת יסוד שמורידה systems ב-production. תכנן תמיד לretries, timeouts, ו-idempotency. payment system שלא עושה את זה יחייב לקוחות פעמיים.
- שימוש ב-timestamps לסדרת events: שעונים בין servers לעולם לא מסונכרנים במדויק. NTP מאזן אבל לא מבטיח. Google Spanner פתר זאת עם TrueTime ו-atomic clocks. בלי תשתית כזו, השתמש ב-Lamport timestamps או vector clocks.
- לסמוך על תיעוד ה-vendor: Jepsen בדק ב-2024 את NATS JetStream ומצא שברירת המחדל היא fsync כל 2 דקות, לא לפני כל ack. crash אחד של kernel = אובדן data שכבר 'אושר'. לפני שבוחרים DB ל-production, בדוק את ניתוח Jepsen שלו בjepsen.io.
סיכום, מה לקחת מהשיעור הזה
Distributed systems הן הבסיס של כל מערכת ב-scale. CAP מלמד אותנו שאי אפשר לקבל הכל, תמיד יש trade-off. PACELC מרחיב ומראה שה-trade-off קיים גם ביום-יום רגיל, לא רק בתקלות. Raft נותן פתרון מעשי לconsensus שניתן לבנות עליו. Saga מחליף את 2PC בעולם של microservices.
Claude יכול לשמש כארכיטקט וירטואלי לכל scenario: הגדר את הדרישות, בקש ניתוח CAP/PACELC, בקש runbook לfailure scenarios, ובקש comparison בין alternatives. ככל שתתאר יותר context, כך הניתוח יהיה מעמיק יותר.
