במאמר הזה מוסבר איך להגדיר חזרה למצב קודם (fallback) ב-MySQL באמצעות רפליקציה הפוכה. המונח "חזרה למצב קודם" מתייחס לתוכנית מגירה לחזרה למסד הנתונים המקורי ב-MySQL, אם נתקלים בבעיות ב-Spanner.
רפליקציה הפוכה שימושית כשנתקלים בבעיות לא צפויות וצריך לחזור למסד הנתונים המקורי של MySQL עם הפרעה מינימלית לשירות. רפליקציה הפוכה מאפשרת לחזור למצב הקודם על ידי שכפול הנתונים שנכתבו ב-Spanner במסד הנתונים של MySQL במקור.
תהליך השכפול ההפוך כולל את השלבים הבאים, שמבוצעים על ידי Spanner_to_SourceDb תבנית Dataflow:
קריאת שינויים מ-Spanner באמצעות Spanner change streams.
מסננים רשומות באמצעות
forward_migrationמצב הסינון.משנים את הנתונים ב-Spanner כך שיתאימו לסכימה של מסד הנתונים במקור באמצעות הכלי להעברת נתונים של Spanner. מידע נוסף מופיע במאמר בנושא טרנספורמציה בהתאמה אישית.
בודקים אם מסד הנתונים של MySQL כבר מכיל נתונים עדכניים יותר עבור המפתח הראשי שצוין. אם כבר קיימים נתונים עדכניים יותר, צינור הנתונים מדלג על אירוע השינוי כדי למנוע החלפה של נתונים חדשים יותר.
כותבים את הנתונים למסד הנתונים של המקור.
שימוש בתבנית Dataflow של Spanner_to_SourceDb
התבנית של Dataflow עוזרת להבטיח עקביות ברמת המפתח הראשי. התבנית יוצרת טבלאות מטא-נתונים, שנקראות טבלאות צל, ב-Spanner. הטבלאות האלה מכילות את חותמת הזמן של השמירה של טרנזקציית הכתיבה האחרונה בשבר של הטבלה הספציפית הזו.
הכתיבה עקבית עד לחותמת הזמן של ה-commit של המפתח הראשי.
רפליקציה הפוכה פועלת כמשימת Dataflow רציפה בסטרימינג.
העבודה קוראת אירועי שינוי מסנכרון שינויים בזרמי נתונים של Spanner, ממירה אותם לסוגי נתונים שתואמים לסכימת מסד הנתונים של המקור וכותבת אותם למסד הנתונים של MySQL. אם מתרחשת שגיאה זמנית באירוע, המשימה מנסה שוב באופן אוטומטי באמצעות ספריית retry/ של תור הודעות שלא נמסרו (DLQ) ב-Cloud Storage. אם מתרחשת שגיאה קבועה באירוע (או אם חורגים ממספר הניסיונות החוזרים), העבודה מנתבת את האירוע לספריית severe/ DLQ לפתרון ידני. מידע נוסף על פתרון בעיות והפעלה מחדש של רשומות שנכשלו זמין במאמר מעקב ופתרון של שגיאות ברפליקציה הפוכה.
לפני שמתחילים
מוודאים שיש קישוריות לרשת בין מסד הנתונים של MySQL לבין פרויקטGoogle Cloud , שבו מופעלות משימות Dataflow.
מוסיפים לרשימת ההיתרים את כתובות ה-IP של ה-worker של Dataflow במכונה של MySQL במקור.
מוודאים שפרטי הכניסה ל-MySQL צוינו בצורה נכונה ב-
source shards file.מוודאים שהמכונה של MySQL מחוברת לאינטרנט ופועלת.
מוודאים שלמשתמש ב-MySQL יש הרשאות
INSERT,UPDATEו-DELETEבמסד הנתונים של MySQL.מוודאים שיש לכם את ההרשאות הנדרשות ב-IAM כדי להריץ תבנית Flex של Dataflow. מידע נוסף זמין במאמר בנושא פיתוח והרצה של תבנית גמישה.
מוודאים שהיציאה
12345פתוחה לתקשורת בין המכונות הווירטואליות של העובדים ב-Dataflow.
התפקידים הנדרשים
-
כדי לקבל את ההרשאות שנדרשות להפעלת הרפליקציה ההפוכה, צריך לבקש מהאדמין להקצות לכם את תפקידי ה-IAM הבאים במכונה:
- משתמש במסד נתונים של Cloud Spanner (
roles/spanner.databaseUser) - Dataflow Developer (
roles/dataflow.developer)
- משתמש במסד נתונים של Cloud Spanner (
-
כדי לוודא שלחשבון השירות של Compute Engine יש את ההרשאות הנדרשות להפעלת הרפליקציה ההפוכה, צריך לבקש מהאדמין להקצות לחשבון השירות של Compute Engine את תפקידי ה-IAM הבאים במכונה:
- משתמש במסד נתונים ב-Cloud Spanner (
roles/spanner.databaseUser) - מגדיר גישה לסודות ב-Secret Manager (
roles/secretmanager.secretAccessor) - צפייה ב-Secret Manager (
roles/secretmanager.viewer)
- משתמש במסד נתונים ב-Cloud Spanner (
הפעלת רפליקה הפוכה
כדי להפעיל רפליקציה הפוכה:
מעלים את קובץ הסשן לקטגוריה של Cloud Storage.
יוצרים התראת Pub/Sub לתיקייה
retryשל ספריית ה-DLQ. כדי לעשות את זה, צריך ליצור נושא Pub/Sub ומינוי Pub/Sub לנושא הזה.יוצרים את תבנית Dataflow ומכינים אותה להפצה. מידע נוסף על תבניות של מבנים
כדי להפעיל את פייפליין זורם של הרפליקציה ההפוכה, מריצים את הפקודה הבאה של
gcloud dataflow flex-template run:gcloud dataflow flex-template run "spanner-to-sourcedb-job" \ --project "PROJECT" \ --region "REGION" \ --template-file-gcs-location "TEMPLATE_SPEC_GCSPATH" \ --parameters "changeStreamName=CHANGE_STREAM_NAME" \ --parameters "instanceId=INSTANCE_ID" \ --parameters "databaseId=DATABASE_ID" \ --parameters "spannerProjectId=SPANNER_PROJECT_ID" \ --parameters "metadataInstance=METADATA_INSTANCE" \ --parameters "metadataDatabase=METADATA_DATABASE" \ --parameters "sourceShardsFilePath=SOURCE_SHARDS_FILE_PATH" \ # All flags after this point are optional [--parameters "startTimestamp=START_TIMESTAMP"] \ [--parameters "endTimestamp=END_TIMESTAMP"] \ [--parameters "shadowTablePrefix=SHADOW_TABLE_PREFIX"] \ [--parameters "sessionFilePath=SESSION_FILE_PATH"] \ [--parameters "filtrationMode=FILTRATION_MODE"] \ [--parameters "shardingCustomJarPath=SHARDING_CUSTOM_JAR_PATH"] \ [--parameters "shardingCustomClassName=SHARDING_CUSTOM_CLASS_NAME"] \ [--parameters "shardingCustomParameters=SHARDING_CUSTOM_PARAMETERS"] \ [--parameters "sourceDbTimezoneOffset=SOURCE_DB_TIMEZONE_OFFSET"] \ [--parameters "dlqGcsPubSubSubscription=DLQ_GCS_PUB_SUB_SUBSCRIPTION"] \ [--parameters "skipDirectoryName=SKIP_DIRECTORY_NAME"] \ [--parameters "maxShardConnections=MAX_SHARD_CONNECTIONS"] \ [--parameters "deadLetterQueueDirectory=DEAD_LETTER_QUEUE_DIRECTORY"] \ [--parameters "dlqMaxRetryCount=DLQ_MAX_RETRY_COUNT"] \ [--parameters "runMode=RUN_MODE"] \ [--parameters "dlqRetryMinutes=DLQ_RETRY_MINUTES"] \ [--parameters "sourceType=SOURCE_TYPE"] \ [--parameters "transformationJarPath=TRANSFORMATION_JAR_PATH"] \ [--parameters "transformationClassName=TRANSFORMATION_CLASS_NAME"] \ [--parameters "transformationCustomParameters=TRANSFORMATION_CUSTOM_PARAMETERS"] \ [--parameters "filterEventsDirectoryName=FILTER_EVENTS_DIRECTORY_NAME"]
המשתנים שחובה להגדיר מתוארים ברשימה הבאה:
-
PROJECT: מזהה הפרויקט ב- Google Cloud . -
REGION: Google Cloud האזור שבו רוצים להריץ את עבודת Dataflow. -
TEMPLATE_SPEC_GCSPATH: הנתיב ב-Cloud Storage לקובץ התבנית של Dataflow שהועלה. -
CHANGE_STREAM_NAME: השם של הזרם לתיעוד שינויים ב-Spanner שהמשימה קוראת ממנו. -
INSTANCE_ID: מזהה המכונה של Spanner. -
DATABASE_ID: מזהה מסד הנתונים ב-Spanner. -
SPANNER_PROJECT_ID: מזהה הפרויקט שבו נמצאים מופעי Spanner. -
METADATA_INSTANCE: המכונה של Spanner שבה מאוחסנים המטא-נתונים שבהם המחבר משתמש כדי לשלוט בצריכת הנתונים של סנכרון שינויים בזרמי נתונים. -
METADATA_DATABASE: מסד הנתונים של Spanner שמאחסן את המטא-נתונים שמשמשים את המחבר לשליטה בצריכת הנתונים של סנכרון שינויים בזרמי נתונים. -
SOURCE_SHARDS_FILE_PATH: הנתיב ב-Cloud Storage שמכיל את פרטי פרופיל החיבור של המקטעים במקור.
ברשימה הבאה מפורטים המשתנים האופציונליים:
-
START_TIMESTAMP: חותמת הזמן שממנה מתחילים לקרוא את השינויים. ברירת המחדל היא ריק. -
END_TIMESTAMP: חותמת הזמן שלפיה יקראו שינויים. אם לא מציינים את מספר השינויים, התהליך קורא שינויים ללא הגבלה. ברירת המחדל היא ריק. -
SHADOW_TABLE_PREFIX: התחילית של שם טבלת הצללים. ברירת מחדל:shadow_. -
SESSION_FILE_PATH: הנתיב לקובץ הסשן ב-Cloud Storage שמכיל את פרטי המיפוי מכלי ההעברה של Spanner. -
FILTRATION_MODE: המצב שקובע איך לסנן רשומות על סמך קריטריונים. המצבים הנתמכים הםnoneו-forward_migration. -
SHARDING_CUSTOM_JAR_PATH: המיקום (הנתיב) ב-Cloud Storage של קובץ ה-JAR בהתאמה אישית שמכיל את הלוגיקה לאחזור מזהה הרסיס. ברירת המחדל היא ריקה. -
SHARDING_CUSTOM_CLASS_NAME: שם המחלקה המוגדר במלואו שכולל את ההטמעה של מזהה השבר (shard) בהתאמה אישית. חובה לכלול את הפרמטר הזה אם מציינים את הפרמטרSHARDING_CUSTOM_JAR_PATH. ברירת המחדל היא ריקה. -
SHARDING_CUSTOM_PARAMETERS: מחרוזת שמכילה פרמטרים מותאמים אישית שמועברים למחלקת הפיצול המותאמת אישית. ברירת המחדל היא ריקה. -
SOURCE_DB_TIMEZONE_OFFSET: ההפרש מאזור הזמן UTC של מסד הנתונים של המקור. לדוגמה,+10:00. ברירת המחדל:+00:00. -
DLQ_GCS_PUB_SUB_SUBSCRIPTION: מינוי Pub/Sub שמשמש במדיניות התראות של Cloud Storage עבור ספריית הניסיון החוזר של תור ה-DLQ כשמריצים במצבregular. מציינים את השם בפורמטprojects/<PROJECT_ID>/subscriptions/<SUBSCRIPTION_ID>. כשמגדירים את הפרמטר הזה, המערכת מתעלמת מהפרמטריםdeadLetterQueueDirectoryו-dlqRetryMinutes. -
SKIP_DIRECTORY_NAME: הספרייה שבה המערכת כותבת רשומות שהיא מדלגת עליהן במהלך שכפול הפוך. ברירת מחדל:skip. -
MAX_SHARD_CONNECTIONS: המספר המקסימלי של חיבורים שמותרים לכל שארד. ברירת המחדל:10000. -
DEAD_LETTER_QUEUE_DIRECTORY: הנתיב לאחסון הפלט של ה-DLQ. ברירת המחדל היא ספרייה במיקום הזמני של משימת Dataflow. -
DLQ_MAX_RETRY_COUNT: מספר הפעמים המקסימלי שהמערכת מנסה שוב שגיאות זמניות דרך ה-DLQ. ברירת המחדל:500. -
RUN_MODE: סוג מצב ההרצה. האפשרויות הנתמכות הןregular,retryDLQו-retryAllDLQ. אפשר להשתמש ב-retryDLQכדי לנסות שוב רשומות שגיאה מהספרייהsevere/לצד צינור עיבוד נתונים פעיל, או ב-retryAllDLQכדי לעבד את הספריותretry/ו-severe/כשצינור עיבוד הנתונים הרגיל נעצר. ברירת מחדל:regular. -
DLQ_RETRY_MINUTES: מספר הדקות בין ניסיונות חוזרים של DLQ. ברירת המחדל:10. -
SOURCE_TYPE: סוג מסד הנתונים של המקור שאליו רוצים לבצע שכפול הפוך. ברירת מחדל:mysql. -
TRANSFORMATION_JAR_PATH: המיקום (הנתיב) ב-Cloud Storage של קובץ ה-JAR בהתאמה אישית שמכיל את לוגיקת הטרנספורמציה בהתאמה אישית לעיבוד רשומות בשכפול הפוך. ברירת המחדל היא ריק. -
TRANSFORMATION_CLASS_NAME: שם המחלקה המוגדר במלואו שמכיל את הלוגיקה של הטרנספורמציה בהתאמה אישית. חובה לכלול את הפרמטר הזה אם מציינים אתTRANSFORMATION_JAR_PATH. ברירת המחדל היא ריק. -
TRANSFORMATION_CUSTOM_PARAMETERS: מחרוזת שמכילה פרמטרים מותאמים אישית שרוצים להעביר למחלקת הטרנספורמציה המותאמת אישית. ברירת המחדל היא ריק. -
FILTER_EVENTS_DIRECTORY_NAME: הספרייה ב-Cloud Storage שבה המערכת כותבת רשומות שסוננו על ידי לוגיקה מותאמת אישית של טרנספורמציה הפוכה. ברירת מחדל:filteredEvents.
-
מעקב אחרי שגיאות ברפליקציה הפוכה ופתרון שלהן
כשמריצים רפליקציה הפוכה מ-Spanner בחזרה ל-MySQL, אם משימת הסטרימינג ב-Dataflow לא מצליחה לכתוב אירוע שינוי במסד הנתונים הראשי של MySQL, היא מסווגת את הכישלון לאחת משתי קטגוריות וכותבת את הרשומה לספריית תור הודעות שלא טופלו בקטגוריה של Cloud Storage:
- שגיאות שאפשר לנסות שוב: כשלים זמניים, כמו מחלוקת על נעילת מסד נתונים של MySQL או פסק זמן בחיבור לרשת. Dataflow כותב את האירועים האלה לספריית תור הודעות שלא טופלו ב-
retry/, ומנסה אותם שוב באופן אוטומטי באותו צינור עיבוד נתונים עד שהם מצליחים או חורגים מ-dlqMaxRetryCount. - שגיאות חמורות: כשלים קבועים שלא ניתן לפתור באמצעות ניסיונות חוזרים אוטומטיים, כמו שגיאות בהמרת סוגי נתונים, שגיאות בתחביר או חריגים בקובצי JAR של טרנספורמציות בהתאמה אישית. Dataflow כותב את האירועים האלה
לספרייה של תור
severe/dead-letter (לדוגמה,gs://MIGRATION_BUCKET/ENV/SERVICE/reverse/DB_SCHEMA/severe/) ומגדיל את מונה המשתמשים המותאם אישיתsevere_error_count.
אי אפשר לפתור שגיאות חמורות באמצעות ניסיונות חוזרים אוטומטיים, ולכן Dataflow מסיר את האירועים שנכשלו מהסטרימינג הפעיל של הרפליקציה ושומר אותם בספרייה severe/. אם לא תטפלו בזה, הרשומות האלה יהיו חסרות במסד הנתונים של MySQL שחזרתם אליו. חשוב לעקוב באופן קבוע אחרי מונה severe_error_count ומדריך severe/ במהלך שכפול הפוך, כדי שתוכלו לפתור ולשחזר אירועי שינוי שנכשלו לפני שתתחילו בהחזרה למצב הקודם.
המונה המותאם אישית severe_error_count של Dataflow הוא מדד מצטבר שמתעד את המספר הכולל של שגיאות חמורות שקרו מאז שהתחילה משימת הסטרימינג. כשמפעילים מחדש ומטפלים ברשומות שנכשלו באמצעות משימת ניסיון חוזר של DLQ, הערך של המונה הזה בפייפליין הזורם המקורי לא יורד. לכן, ספריית ה-DLQ של Cloud Storage לשגיאות חמורות (gs://MIGRATION_BUCKET/ENV/SERVICE/reverse/DB_SCHEMA/severe/) היא המקור המהימן היחיד שמאפשר לדעת אם יש שגיאות שלא טופלו.
הפעלה מחדש של רשומות שנכשלו
כשמופיעות רשומות שנכשלו בספריית DLQ חמורה, צריך לבדוק את קובצי שגיאות ה-JSON ב-Cloud Storage, לזהות את שורש הבעיה ולפתור את הבעיה הבסיסית.
כדי להפעיל מחדש רשומות DLQ מתוקנות ב-MySQL, מפעילים משימת Dataflow חדשה באחד ממצבי ההפעלה הבאים:
- מצב
retryDLQ: מריצים את המצב הזה כמשימה באצווה לצד פייפליין זורם פעיל, כדי לעבד קובצי שגיאות בספרייהsevere/בלי לעצור את הרפליקציה ההפוכה בזמן אמת. כדאי להפעיל את המצב הזה אחרי שפותרים את שורש הבעיות שגרמו לשגיאות החמורות. - מצב
retryAllDLQ: אם פייפליין זורם הרגיל שלך מושבת, השתמש במצב הזה כדי לעבד את הספריותretry/ו-severe/. לא מומלץ להריץ אתretryAllDLQבמקביל לפייפליין פעיל, כי זה יגרום למחלוקות לגבי קבצים ולבעיות בעיבוד.
כדי להפעיל מחדש את העבודה של תור הודעות להמתנה (DLQ) של שכפול הפוך באמצעות ה-CLI של gcloud, מריצים את הפקודה הבאה:
gcloud dataflow flex-template run "spanner-to-sourcedb-retry-job" \
--project "PROJECT" \
--region "REGION" \
--template-file-gcs-location "TEMPLATE_SPEC_GCSPATH" \
--parameters "changeStreamName=CHANGE_STREAM_NAME" \
--parameters "instanceId=INSTANCE_ID" \
--parameters "databaseId=DATABASE_ID" \
--parameters "spannerProjectId=SPANNER_PROJECT_ID" \
--parameters "metadataInstance=METADATA_INSTANCE" \
--parameters "metadataDatabase=METADATA_DATABASE" \
--parameters "sourceShardsFilePath=SOURCE_SHARDS_FILE_PATH" \
--parameters "deadLetterQueueDirectory=DLQ_DIRECTORY" \
--parameters "runMode=retryDLQ"
מחליפים את מה שכתוב בשדות הבאים:
-
PROJECT: מזהה הפרויקט ב- Google Cloud . -
REGION: האזור ב- Google Cloud שבו רוצים להריץ את המשימה ב-Dataflow. -
TEMPLATE_SPEC_GCSPATH: הנתיב ב-Cloud Storage לקובץ של תבנית Dataflow שהועלה ל-Staging. -
CHANGE_STREAM_NAME: השם של זרם השינויים ב-Spanner שהמשימה קוראת ממנו. -
INSTANCE_ID: מזהה מכונת Spanner. -
DATABASE_ID: מזהה מסד הנתונים של Spanner. -
SPANNER_PROJECT_ID: מזהה הפרויקט שבו נמצאים מופעי Spanner. -
METADATA_INSTANCE: המכונה של Spanner שבה מאוחסנים המטא-נתונים שבהם המחבר משתמש כדי לשלוט בצריכת הנתונים של סנכרון שינויים בזרמי נתונים. -
METADATA_DATABASE: מסד הנתונים של Spanner שמאחסן את המטא-נתונים שמשמשים את המחבר לשליטה בצריכת הנתונים של סנכרון שינויים בזרמי נתונים. -
SOURCE_SHARDS_FILE_PATH: הנתיב ב-Cloud Storage שמכיל את פרטי פרופיל החיבור של מקטעי המקור. -
DLQ_DIRECTORY: הנתיב ב-Cloud Storage לספריית התור להודעות שלא טופלו, שמכילה את קובצי השגיאות החמורות שרוצים לנסות שוב.