מעבר פעיל לגיבוי ויתירות כשל ברפליקציה באמצעות 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: הגרסה של הנתונים עם חותמת הזמן של השמירה האחרונה היא הנתונים שנשמרים
  • 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. כדאי ליצור הגדרה חדשה של ספק/מנוי כדי לשמור על זמינות גבוהה ועל יכולת התאוששות מאסון.

  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. מעבירים את האפליקציה לכתיבה לצומת החדש.

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