מעבר לגיבוי כשל עם שכפול pglogical

בוחרים גרסת תיעוד:

בדף הזה מוסבר איך לבצע מעבר ידני (switchover) ומעבר אוטומטי (failover) עם רפליקציה של pglogical.

לפני שמתחילים

אחרי שמגדירים את הרפליקציה של pglogical ויש פתרון מעשי לזמינות גבוהה (HA) ולתוכנית התאוששות מאסון (DR), ובהנחה שהרפליקציה הלוגית לא מספקת רפליקציה true ומקיפה של כל האובייקטים של מסד הנתונים, צריך לבדוק את ההגדרה הזו לפני שמתחילים להשתמש בה.

מידע נוסף על התוסף pglogical זמין במאמר מידע על pglogical.

למידע על שכפול נתונים באמצעות pglogical, אפשר לעיין במאמרים שכפול נתונים בין AlloyDB ל-PostgreSQL לבין AlloyDB Omni ושכפול נתונים בין AlloyDB Omni לבין מסדי נתונים אחרים.

מעבר לגיבוי הנתונים עם שכפול pglogical

מעבר הוא תהליך מבוקר שמשמש להחלפת התפקידים בין מסדי הנתונים של הספק והמנוי. כשמבצעים מעבר, התפקידים של שני מסדי הנתונים, ספק ומנוי, מתהפכים. הספק הופך למנוי והמנוי הופך לספק.

היכולת הזו חשובה לשדרוגים של מערכת ההפעלה, לשדרוגים של PostgreSQL או לבדיקת יתירות כשל.

כדי לעשות את זה בהגדרות של רפליקציה חד-כיוונית, צריך להגדיר קשר חדש בין ספק למנוי ולהסיר את הקשר הישן.

בניית ההגדרה החדשה של הספק/המנוי

  1. עוצרים את הכתיבה של האפליקציה למערכת הספק כדי למנוע שינויים נוספים במסד הנתונים, ובודקים את השהיית הרפליקציה כדי לוודא שכל הטרנזקציות מופעלות מחדש בצומת המנוי:

    SELECT application_name,
        state,
        sync_state,
        client_addr,
        client_hostname,
        pg_wal_lsn_diff(pg_current_wal_lsn(),sent_lsn) AS sent_lag,
        pg_wal_lsn_diff(sent_lsn,flush_lsn) AS receiving_lag,
        pg_wal_lsn_diff(flush_lsn,replay_lsn) AS replay_lag,
        pg_wal_lsn_diff(pg_current_wal_lsn(),replay_lsn) AS total_lag,
        now()-reply_time AS reply_delay
    FROM pg_stat_replication
    ORDER BY client_hostname;
    

    כשכל שדות ההשהיה מציגים אפס, הרפליקציה מעודכנת ומסד הנתונים מוכן למעבר.

    הפלט אמור להיראות כך:

    -[ RECORD 1 ]----+------------------------------
    application_name | test_sub_1
    state            | streaming
    sync_state       | async
    client_addr      | 10.45.0.80
    client_hostname  | 
    sent_lag         | 0
    receiving_lag    | 0
    replay_lag       | 0
    total_lag        | 0
    reply_delay      | 00:00:26.203433
    
  2. המרת מסד הנתונים של המנויים למסד נתונים של ספק:

    1. להפסיק את המינוי הקיים של המנוי.
    2. מוסיפים את קבוצת הרפליקציה, אם צריך.
    3. מוסיפים את הטבלאות הנדרשות לקבוצת הרפליקציה.
    4. יוצרים מינוי חדש למנויים במסד הנתונים החדש של המנויים.
    5. מפנים את האפליקציות לספק החדש.
  3. מפסיקים את המינוי במסד הנתונים של המנויים הקיימים, שהופך לספק החדש:

    SELECT pglogical.alter_subscription_disable(SUBSCRIPTION_NAME);
    
  4. (אופציונלי) יוצרים קבוצת רפליקציה שתואמת להגדרה של מסד הנתונים המקורי של הספק. הפעולה הזו לא נדרשת אם אתם משתמשים בקבוצות השכפול שמוגדרות כברירת מחדל:

    SELECT pglogical.create_replication_set(REPLICATION_SET_NAME);
    
  5. מוסיפים טבלאות לקבוצת השכפול:

    SELECT pglogical.replication_set_add_table(REPLICATION_SET_NAME, TABLE_NAME);
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫REPLICATION_SET_NAME: השם של קבוצת הרפליקות.
    • ‫TABLE_NAME: שם הטבלה של בעלי הסכימה. לדוגמה, ARRAY['public'].`
  6. במסד הנתונים החדש של המנויים, שהיה בעבר מסד הנתונים של הספק, יוצרים את המינוי החדש עם האפשרות synchronize_data שמוגדרת לערך false כדי למנוע את הטעינה הראשונית של הטבלה:

    SELECT pglogical.create_subscription (
               subscription_name := '<subscription name>',
               replication_sets := array['default'],
               synchronize_data := false,
               provider_dsn := 'host=<hostname or IP> port=5432 
               dbname=<db name> user=pglogical_replication password=<password>');
    
  7. בודקים אם המינוי פועל בצומת של הספק:

    SELECT application_name,
        state,
        sync_state,
        client_addr,
        client_hostname,
        pg_wal_lsn_diff(pg_current_wal_lsn(),sent_lsn) AS sent_lag,
        pg_wal_lsn_diff(sent_lsn,flush_lsn) AS receiving_lag,
        pg_wal_lsn_diff(flush_lsn,replay_lsn) AS replay_lag,
        pg_wal_lsn_diff(pg_current_wal_lsn(),replay_lsn) AS total_lag,
        now()-reply_time AS reply_delay
    FROM pg_stat_replication
    ORDER BY client_hostname;
    
  8. אם השכפול פועל, משנים את מחרוזות החיבור של האפליקציה כך שישתמשו במסד הנתונים החדש של הספק ומפעילים מחדש את רמות האפליקציה.

אם משנים את הנתונים בצומת של הספק הישן אחרי שהמנוי הופסק, השינויים האלה לא משוכפלים וזה גורם לאובדן נתונים. אם יש שינויים בנתונים שלא שוכפלו במסד הנתונים של הספק המקורי, או אם הספק המקורי (המנוי החדש) לא נמצא במצב שתואם למסד הנתונים של הספק החדש (המנוי הישן), צריך לבנות את מסד הנתונים של המנוי החדש מחדש.

הסרת הספק והמינוי הישנים

אם רוצים שכפול חד-כיווני, צריך להסיר את ההגדרה הישנה של הספק או המנוי.

  1. הסרת המינוי הישן אצל הספק החדש:

    SELECT pglogical.drop_subscription('<subscription name>')
    
  2. מסירים את קבוצת השכפול מהמנוי החדש או מסירים את כל הטבלאות מקבוצת השכפול:

    SELECT pglogical.drop_replication_set('<replication set name>')
    
    SELECT pglogical.replication_set_remove_table('<replication set name>','<table name>')
    

רפליקציה דו-כיוונית

כדי לעבור בלי זמן השבתה, או כדי לוודא שלא יאבדו נתונים בגלל שינויים לא מתוכננים בנתונים, צריך להשתמש ברפליקציה דו-כיוונית. כשמטמיעים שכפול דו-כיווני, צריך להביא בחשבון את פתרון הקונפליקטים, אלא אם יש אמצעי בקרה מחמירים למניעת גישת כתיבה לשני הצמתים בו-זמנית.

כדי להגדיר את פתרון ההתנגשויות, אפשר להשתמש בהגדרות הבאות של pglogical.conflict_resolution:

  • ‫error: המינוי של המשתמש מופסק כשמזוהה התנגשות.
  • ‫apply_remote: תמיד להחיל את השינויים הנכנסים, בלי קשר לנתונים במסד הנתונים של המנוי. זוהי הגדרת ברירת המחדל.
  • keep_local: תמיד להתעלם מהנתונים הנכנסים שמתנגשים ולמחוק את השינוי שמתנגש.
  • ‫last_update_wins: הנתונים שמתבצעת לגביהם פעולת commit הם הנתונים שכוללים את חותמת הזמן של ה-commit האחרון
  • ‫first_update_wins: גרסת הנתונים עם חותמת הזמן הישנה ביותר היא הגרסה שמועברת.

כדי להגדיר רפליקציה דו-כיוונית, מגדירים את הספק והמנוי כך שהרפליקציה תתבצע בשני הכיוונים. המנוי המקורי הופך גם לספק עם אותה קבוצת שכפול כמו הספק המקורי. כדי ליצור קבוצת רפליקציה שמשכפלת את קבוצת הרפליקציה המקורית במסד הנתונים של הספק הראשוני, עיינו בקטע יצירת טבלה והוספה שלה לקבוצת הרפליקציה שמוגדרת כברירת מחדל במסד הנתונים של ספק AlloyDB ל-PostgreSQL.

בספק המקורי, אתם צריכים להוסיף מנוי חדש. כדי ליצור מנוי חדש, פועלים לפי ההוראות במאמר יצירת צומת ומנוי במסד הנתונים של המנויים ב-AlloyDB Omni, ומוודאים שהפרמטר synchronize_data של הפקודה pglogical.create_subscription מוגדר לערך false. כך נמנעת ההעתקה הראשונית של הנתונים בטבלה.

מעבר לגיבוי בעת כשל עם רפליקציה של pglogical

יתירות כשל מתרחשת כשמסד הנתונים של הספק לא זמין מסיבה כלשהי, ואתם צריכים להעביר את האפליקציה לשימוש במסד הנתונים של המנוי.

כדי למנוע מצב שבו נתונים כפולים יוחלו בטעות על מסד הנתונים של המינוי שעבר גיבוי אוטומטי, צריך להשבית את המינוי. כך מוודאים ששינויים מספק ששוחזר לא יחולו בטעות כשהספק יהיה זמין שוב.

  1. עוצרים את המנוי, test_sub_1:

    SELECT pglogical.alter_subscription_disable(`test_sub_1`);
    
  2. בודקים שהסטטוס הוא disabled:

    SELECT pglogical.show_subscription_status('test_sub_1');
    

    הפלט אמור להיראות כך:

    show_subscription_status                                                                           
    ----------------------------------------------------------------------------
    (test_sub1,disabled,subscriber,"host=10.45.0.108 port=5432 dbname=my_test_db user=pglogical_replication",subscriber,{failover_set},{all})
    
  3. בודקים את מילת המפתח המושבתת בפלט הסטטוס.

  4. ליצור הגדרה חדשה של ספק/מנוי כדי לשמור על זמינות גבוהה ויכולת התאוששות מאסון (DR).

  5. יוצרים קבוצת רפליקציה חדשה שמכילה את כל הטבלאות ששוכפלו במקור, כדי ליצור מנוי חדש כשמסד הנתונים של הספק הישן משוחזר ומומר למנוי חדש, או כשנוצר מנוי חדש.

  6. מגדירים את המנוי.

  7. אם אפשר לשחזר את מסד הנתונים של הספק הקודם לזמן הכשל, צריך להגדיר את מסד הנתונים הזה כמנוי החדש. כדי ליצור מינוי, פועלים לפי אותם השלבים ומגדירים את הפרמטר synchronize_data של הפקודה pglogical.create_subscription לערך false כדי להימנע מהעתקה של הטבלה הראשונית.

  8. כדי למנוע הצטברות של קובצי WAL, מסירים את הגדרת הספק הישנה בצומת ששוחזר.

  9. אם אתם משתמשים במסד הנתונים הישן של הספק, אתם יכולים להסיר את כל קבוצת השכפול או להסיר את כל הטבלאות מקבוצת השכפול אחת אחת:

    SELECT pglogical.drop_replication_set('<replication set name>')
    
    SELECT pglogical.replication_set_remove_table('<replication set name>','<table name>')
    
  10. מעבירים את האפליקציה לכתיבה לצומת החדש.

המאמרים הבאים