Quy trình switchover failover streaming replication

Bài viết được thực hiện theo yêu cầu của bạn Lê Văn Tú trong group “Kho tài liệu kiến thức về database”

Ở bài viết trước, tôi đã hướng dẫn các bạn xây dựng hệ thống dự phòng cho PostgreSQL bằng Streaming Replication. Trong bài viết này, tôi sẽ hướng dẫn các bạn xử lý trong 2 tình huống phổ biến nhất cần đến Streaming Replication:

Đọc thêm  Cấu hình Streaming Replication trong PostgreSQL 13

   Tình huống 1: Failover

Đây là tình huống khi database master gặp trục trặc, không thể hoạt động tiếp được. Chúng ta cần phải kích hoạt database slave (dự phòng) lên thành database master mới.

   Tình huống 2: Switchover

Đây là tình huống, chúng ta sẽ chuyển đổi vai trò giữa database master và database slave cho nhau (master thành slave, slave thành master). Tình huống này thường gặp khi chúng ta cần kiểm thử slave có đủ sẵn sàng trong trường hợp master bị hỏng hay không, hoặc khi chúng ta cần bảo dưỡng master, trong khi ứng dụng vẫn có thể kết nối với slave và làm việc bình thường.


   Mô hình triển khai

Mô hình mà tôi sử dụng để thực hiện bài lab này như sau

Thông tin Master:

IP: 192.168.56.10

OS: Oracle Linux 7.9

Version PostgreSQL: 13

Thông tin Slave

IP: 192.168.56.11

OS: Oracle Linux 7.9

Version PostgreSQL: 13


   Quy trình Failover

   Bài toán đặt ra

Giả sử server master của tôi bị trục trặc và hiện đã không thể khởi động lên được. Như các bạn đã biết, dữ liệu trên database slave giống y hệt với database master, tuy nhiên slave chỉ cho phép đọc thôi, không ghi được. Tôi cần cấu hình database slave có thể đọc/ghi được, để cho ứng dụng kết nối vào slave, thay thế tạm thời cho master.

   Thực hiện trên master

Để giả lập tình huống database master bị lỗi, tôi sẽ stop database master đi

$ pg_ctl stop
waiting for server to shut down.... done
server stopped

   Thực hiện trên Slave

Kiểm tra thư mục lưu archive log đã có hay chưa

show archive_command ;
archive_command
----------------------------------------------------------
test ! -f /backup/archive/%f && cp %p /backup/archive/%f
ls -l /backup/archive

Thực hiện promote database slave thành master

pg_ctl promote
waiting for server to promote.... done
server promoted

Kiểm tra trong log

2021-08-07 10:11:54.443 +07 [12591] LOG: received promote request
2021-08-07 10:11:54.443 +07 [12591] LOG: redo done at 0/4000028
2021-08-07 10:11:54.443 +07 [12591] LOG: last completed transaction was at log time 2021-08-07 10:09:49.032965+07
2021-08-07 10:11:54.449 +07 [12591] LOG: selected new timeline ID: 2
2021-08-07 10:11:55.216 +07 [12591] LOG: archive recovery complete
2021-08-07 10:11:55.238 +07 [12587] LOG: database system is ready to accept connections

Sau khi promote, bạn sẽ thấy file standby.signal cũng biến mất

File này không còn có nghĩa là PostgreSQL đã coi slave là 1 database độc lập, có thể đọc ghi được rồi. Thử kiểm tra lại nhé

   Kiểm tra lại:

$ psql

Tạo thử dữ liệu

postgres=# create table test123(id int4);
CREATE TABLE
postgres=#
postgres=#
postgres=# insert into test123 values (1);
INSERT 0 1
postgres=# insert into test123 values (2);
INSERT 0 1
postgres=# insert into test123 values (3);
INSERT 0 1
postgres=# insert into test123 values (4);
INSERT 0 1
postgres=# select * from test123;
id
----
1
2
3
4
(4 rows)

Các bạn thấy đó, database slave giờ đã đọc/ghi được và ứng dụng có thể kết nối vào đó được rồi.


   Quy trình Switchover

   Bài toán đặt ra

Hiện tại, bạn kiểm tra thì database slave vẫn đang đồng bộ bình thường với database master. Tuy nhiên, bạn vẫn lăn tăn việc, nếu như có sự cố trên master thực sự xảy ra, liệu slave có đủ sẵn sàng để hoạt động thay thế không?
Lúc này, bạn cần thử diễn tập switchover (tráo đổi vai trò) database, để đưa slave thành master và ngược lại. Sau khi switchover, bạn sẽ cho ứng dụng kết nối vào slave (lúc này là master mới), và kiểm tra toàn bộ nghiệp vụ xem slave có đáp ứng được hay không.

   Kiểm tra Slave:

Việc đầu tiên bạn cần làm là kiểm tra xem Standby đã đồng bộ realtime với master hay chưa

select * from pg_stat_wal_receiver;
select pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn(), pg_last_xact_replay_timestamp();

Để hiểu ý nghĩa của những câu lệnh này các bạn có thể đọc bài viết sau của tôi nhé:

Đọc thêm  Monitor Streaming Replication trong PostgreSQL

   Thực hiện trên Master

Sau khi đã chắc chắn là database slave đang đồng bộ realtime với master, các bạn hãy tắt database master đi

$ pg_ctl stop

Backup lại file postgresql.conf

cd $PGDATA
cp postgresql.conf postgresql.conf.old

   Tiến hành promote Slave

Kiểm tra thư mục lưu archive log đã có hay chưa

show archive_command ;
archive_command
----------------------------------------------------------
test ! -f /backup/archive/%f && cp %p /backup/archive/%f
ls -l /backup/archive

Kiểm tra lần cuối xem slave đã đọc đến WAL record cuối cùng được master gửi sang hay chưa. Bước này quan trọng nè.

postgres=# select pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn(), pg_last_xact_replay_timestamp();
-[ RECORD 1 ]-----------------+------------------------------
pg_last_wal_receive_lsn       | 0/301B510
pg_last_wal_replay_lsn        | 0/301B510
pg_last_xact_replay_timestamp | 2021-08-07 10:06:55.438858+07

Các bạn thấy 2 chỉ số pg_last_wal_receive_lsn và pg_last_wal_replay_lsn  bằng nhau là được.

Cuối cùng là tiến hành đưa standby lên thành master mới

$ pg_ctl promote
waiting for server to promote.... done 
server promoted

Kiểm tra trong log

2021-08-07 10:11:51.621 +07 [13378] FATAL: could not connect to the primary server: could not connect to server: Connection refused
Is the server running on host "192.168.56.10" and accepting
TCP/IP connections on port 5432?
2021-08-07 10:11:54.443 +07 [12591] LOG: received promote request
2021-08-07 10:11:54.443 +07 [12591] LOG: redo done at 0/4000028
2021-08-07 10:11:54.443 +07 [12591] LOG: last completed transaction was at log time 2021-08-07 10:09:49.032965+07
2021-08-07 10:11:54.449 +07 [12591] LOG: selected new timeline ID: 2
2021-08-07 10:11:55.216 +07 [12591] LOG: archive recovery complete
2021-08-07 10:11:55.238 +07 [12587] LOG: database system is ready to accept connections

Như vậy là database slave đã thành master mới rồi đó. Tuy nhiên bây giờ mà bạn start master cũ lên thì sẽ có 2 con master chạy cùng lúc đấy. Vậy việc tiếp theo là phải cấu hình để master cũ thành slave mới.

   Đưa Master thành Slave

Sửa lại file postgresql.conf, bạn thêm vào dòng sau

primary_conninfo = ‘user=replication password=Abcd1234 channel_binding=prefer host=192.168.56.11 port=5432 sslmode=prefer sslcompression=0 ssl_min_protocol_version=TLSv1.2 gssencmode=prefer krbsrvname=postgres target_session_attrs=any’

Trong đó, host=192.168.56.11 chính là IP của slave cũ (hay master mới).

Tạo file standby.signal

touch standby.signal

File này để báo hiệu cho biết đây là 1 database slave khi khởi động.

Bây giờ bạn có thể khởi động slave mới (hay master cũ) được rồi đấy

$ pg_ctl start
waiting for server to start....2021-08-07 10:26:25.005 +07 [12043] LOG:  redirecting log output to logging collector process
2021-08-07 10:26:25.005 +07 [12043] HINT:  Future log output will appear in directory "log".
 done
server started

Trong log sẽ thấy như sau:

2021-08-07 10:26:25.006 +07 [12043] LOG: starting PostgreSQL 13.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
2021-08-07 10:26:25.006 +07 [12043] LOG: listening on IPv4 address "0.0.0.0", port 5432
2021-08-07 10:26:25.006 +07 [12043] LOG: listening on IPv6 address "::", port 5432
2021-08-07 10:26:25.008 +07 [12043] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2021-08-07 10:26:25.012 +07 [12043] LOG: listening on Unix socket "/tmp/.s.PGSQL.5432"
2021-08-07 10:26:25.015 +07 [12045] LOG: database system was shut down at 2021-08-07 10:10:56 +07
2021-08-07 10:26:25.015 +07 [12045] LOG: entering standby mode
2021-08-07 10:26:25.017 +07 [12045] LOG: consistent recovery state reached at 0/40000A0
2021-08-07 10:26:25.017 +07 [12045] LOG: invalid record length at 0/40000A0: wanted 24, got 0
2021-08-07 10:26:25.018 +07 [12043] LOG: database system is ready to accept read only connections
2021-08-07 10:26:55.095 +07 [12083] LOG: fetching timeline history file for timeline 2 from primary server
2021-08-07 10:26:55.117 +07 [12083] LOG: started streaming WAL from primary at 0/4000000 on timeline 1
2021-08-07 10:26:55.117 +07 [12083] LOG: replication terminated by primary server
2021-08-07 10:26:55.117 +07 [12083] DETAIL: End of WAL reached on timeline 1 at 0/40000A0.
2021-08-07 10:26:55.118 +07 [12045] LOG: new target timeline is 2
2021-08-07 10:26:55.118 +07 [12083] LOG: restarted WAL streaming at 0/4000000 on timeline 2
2021-08-07 10:26:55.874 +07 [12045] LOG: redo starts at 0/40000A0

   Kiểm tra lại

Thực hiện insert dữ liệu trên master mới (slave cũ)

postgres=# create table test1234(id int4);
CREATE TABLE
postgres=#
postgres=#
postgres=# insert into test1234 values (1);
INSERT 0 1
postgres=# insert into test1234 values (2);
INSERT 0 1
postgres=# insert into test1234 values (3);
INSERT 0 1
postgres=# insert into test1234 values (4);
INSERT 0 1

Kiểm tra dữ liệu xem đã có trên slave mới (master cũ) hay chưa

postgres=# select * from test1234;
 id
----
  1
  2
  3
  4
(4 rows)

Như vậy tôi đã xong bài lab rồi đó, nếu các bạn có câu hỏi hay vấn đề gì chưa rõ, có thể để lại bình luận bên dưới bài viết hoặc vào trong group “Kho tài liệu kiến thức Database” nhé.

Nguồn: https://dangxuanduy.com/

   Hãy tham gia group “Kho tài liệu kiến thức database” để cùng học hỏi và chia sẻ nhé.

Xin cho tôi được biết, bạn cảm thấy bài viết này như thế nào? Ý kiến của bạn sẽ giúp tôi nâng cao chất lượng bài viết của mình.

    Hãy chia sẻ bài viết này nếu bạn thấy có ích nhé

     

    0 0 votes
    Article Rating
    Subscribe
    Notify of
    guest
    0 Comments
    Inline Feedbacks
    View all comments