תבנית Transactional Outbox: פרסום אירועים אמין במארג מיקרו-שירותים
בארכיטקטורת מיקרו-שירותים מבוססת אירועים (Event-Driven Architecture), שירותים מפיצים אירועים באופן קבוע (OrderCreated, PaymentProcessed) כדי לתקשר שינויי מצב באופן מנותק.
עם זאת, הבטחת אמינות מלאה בפרסום אירועים מציבה אתגר קריטי: כיצד להבטיח שעדכון מסד הנתונים ופרסום האירוע יצליחו שניהם יחד או ייכשלו שניהם יחד?
אם מיקרו-שירות מעדכן את מסד הנתונים המקומי שלו (PostgreSQL או MySQL) ולאחר מכן מנסה לשלוח הודעה ברשת לברוקר (כגון Apache Kafka או RabbitMQ), תקלת רשת עלולה לגרום לחוסר עקביות בנתונים.
כדי לפתור זאת, מועצבת תבנית Transactional Outbox.
הבעיה: בעיית הכתיבה הכפולה (Dual-Write Problem)
כאשר שירות מנסה לבצע שתי כתיבות נפרדות:
- שמירת הנתונים במסד הנתונים המקומי.
- שליחת האירוע לברוקר ההודעות.
אם שמירת הנתונים מצליחה אך שליחת ההודעה ל-Kafka נכשלת עקב בעיית רשת, הנתונים נשמרים במסד הנתונים אך השירותים התלויים לא יעודכנו לעולם. תוצאה: חוסר עקביות בנתונים.
מהי תבנית Transactional Outbox?
התבנית מנצלת את תכונת ה-ACID Transactions המקומית של מסדי נתונים יחסיים.
במקום לשלוח את ההודעה ישירות ברשת, השירות כותב את האירוע לטבלה ייעודית בשם Outbox Table בתוך אותה עסקת ACID מקומית שבה נשמרת הישות העסקית.
בזכות מנגנון ה-ACID: שתי הכתיבות מאושרות יחד או מבוטלות יחד.
לאחר מכן, תהליך רקע נפרד (Message Relay) קורא את הטבלה ומעביר את ההודעות לברוקר.
אסטרטגיות ממסר: Polling Publisher מול CDC (Debezium)
1. דגימה תקופתית (Polling Publisher)
תהליך רקע קורא תקופתית רשומות שלא עובדו (SELECT * FROM outbox_events WHERE processed = FALSE), שולח ל-Kafka ומעדכן את הסטטוס.
- יתרונות: קל ליישום ללא תשתית נוספת.
- חסרונות: השהיה ועומס קריאות על מסד הנתונים.
2. תפיסת שינויי נתונים (CDC עם Debezium)
Debezium קורא ישירות את יומן העסקאות (PostgreSQL WAL) ומשדר את השינויים בזמן אמת ל-Kafka.
- יתרונות: השהיה כמעט אפסית ללא עומס על האפליקציה.
- חסרונות: דורש תשתית Kafka Connect ו-Debezium.
סיכום
תבנית Transactional Outbox היא תבנית חיונית להבטחת עקביות סופית (Eventual Consistency) ואמינות במערכות מיקרו-שירותים מבוזרות.