MySQL master-slave replication khá dễ dàng và đơn giản để thiết lập. Đây là lý do chính tại sao mọi người chọn công nghệ này là bước đầu tiên để đạt được tính khả dụng của cơ sở dữ liệu tốt hơn. Tuy nhiên, nó phải trả giá bằng sự phức tạp trong quản lý và bảo trì; quản trị viên có quyền duy trì tính toàn vẹn của dữ liệu, đặc biệt là trong quá trình chuyển đổi dự phòng, khôi phục dự phòng, bảo trì, nâng cấp, v.v.
Có rất nhiều bài báo mô tả về cách thực hiện hoạt động chuyển đổi dự phòng để thiết lập nhân rộng. Chúng tôi cũng đã đề cập đến chủ đề này trong bài đăng trên blog này, Giới thiệu về Chuyển đổi dự phòng cho MySQL Replication - Blog 101. Trong bài đăng blog này, chúng tôi sẽ đề cập đến các tác vụ sau thảm họa khi khôi phục về cấu trúc liên kết ban đầu - thực hiện hoạt động dự phòng.
Tại sao chúng ta cần dự phòng?
Thủ lĩnh nhân bản (chính) là nút quan trọng nhất trong thiết lập nhân bản. Nó yêu cầu các thông số kỹ thuật phần cứng tốt để đảm bảo nó có thể xử lý ghi, tạo các sự kiện sao chép, xử lý các lần đọc quan trọng, v.v. một cách ổn định. Khi cần chuyển đổi dự phòng trong quá trình khôi phục hoặc bảo trì sau thảm họa, có thể không hiếm khi thấy chúng tôi quảng bá một nhà lãnh đạo mới với phần cứng kém hơn. Tình trạng này có thể tạm thời ổn, tuy nhiên về lâu dài, bản gốc được chỉ định phải được đưa trở lại để dẫn đầu bản sao sau khi nó được coi là khỏe mạnh.
Trái ngược với chuyển đổi dự phòng, hoạt động dự phòng thường xảy ra trong môi trường được kiểm soát thông qua chuyển đổi, nó hiếm khi xảy ra ở chế độ hoảng loạn. Điều này cho phép nhóm vận hành một thời gian để lên kế hoạch cẩn thận và tập dượt cho quá trình chuyển đổi suôn sẻ. Mục tiêu chính chỉ đơn giản là đưa bản gốc tốt trở lại trạng thái mới nhất và khôi phục thiết lập sao chép về cấu trúc liên kết ban đầu của nó. Tuy nhiên, có một số trường hợp dự phòng là rất quan trọng, chẳng hạn như khi bản chính mới được thăng cấp không hoạt động như mong đợi và ảnh hưởng đến dịch vụ cơ sở dữ liệu tổng thể.
Làm thế nào để thực hiện dự phòng một cách an toàn?
Sau khi chuyển đổi dự phòng xảy ra, bản chính cũ sẽ ra khỏi chuỗi sao chép để bảo trì hoặc phục hồi. Để thực hiện chuyển đổi, người ta phải làm như sau:
- Cung cấp trạng thái chính xác cho trang cái cũ, bằng cách biến nó thành máy chủ cập nhật nhất.
- Dừng ứng dụng.
- Xác minh rằng tất cả các nô lệ đã được bắt kịp.
- Thăng cấp chủ cũ làm lãnh đạo mới.
- Bổ nhiệm tất cả nô lệ cho chủ mới.
- Khởi động ứng dụng bằng cách viết thư cho chủ mới.
Hãy xem xét thiết lập sao chép sau:
"A" là một cái chính cho đến khi một sự kiện đầy đĩa gây ra sự tàn phá cho chuỗi sao chép. Sau một sự kiện chuyển đổi dự phòng, cấu trúc liên kết sao chép của chúng tôi được dẫn đầu bởi B và sao chép lên C cho đến E. Bài tập dự phòng sẽ đưa A trở lại là nhà lãnh đạo và khôi phục cấu trúc liên kết ban đầu trước thảm họa. Lưu ý rằng tất cả các nút đang chạy trên MySQL 8.0.15 với GTID được bật. Phiên bản chính khác nhau có thể sử dụng các lệnh và bước khác nhau.
Mặc dù đây là kiến trúc của chúng ta bây giờ trông như thế nào sau khi chuyển đổi dự phòng (lấy từ chế độ xem Topo của ClusterControl):
Cấp phép nút
Trước khi A có thể là một cái chính, nó phải được cập nhật với trạng thái cơ sở dữ liệu hiện tại. Cách tốt nhất để làm điều này là biến A thành nô lệ cho chủ đang hoạt động, B. Vì tất cả các nút được định cấu hình bằng log_slave_updates =ON (có nghĩa là một nô lệ cũng tạo ra nhật ký nhị phân), chúng tôi thực sự có thể chọn các nô lệ khác như C và D như nguồn chân lý cho quá trình đồng bộ hóa ban đầu. Tuy nhiên, càng gần chủ hoạt động thì càng tốt. Hãy nhớ đến tải bổ sung mà nó có thể gây ra khi sao lưu. Phần này chiếm hầu hết thời gian dự phòng. Tùy thuộc vào trạng thái nút và kích thước tập dữ liệu, việc đồng bộ hóa trang cái cũ có thể mất một chút thời gian (có thể là hàng giờ và ngày).
Sau khi sự cố trên "A" được giải quyết và sẵn sàng tham gia chuỗi sao chép, bước đầu tiên tốt nhất là cố gắng sao chép từ "B" (192.168.0.42) với câu lệnh CHANGE MASTER:
mysql> SET GLOBAL read_only = 1; /* enable read-only */
mysql> CHANGE MASTER TO MASTER_HOST = '192.168.0.42', MASTER_USER = 'rpl_user', MASTER_PASSWORD = 'p4ss', MASTER_AUTO_POSITION = 1; /* master information to connect */
mysql> START SLAVE; /* start replication */
mysql> SHOW SLAVE STATUS\G /* check replication status */
Nếu quá trình sao chép hoạt động, bạn sẽ thấy thông tin sau trong trạng thái sao chép:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Nếu sao chép không thành công, hãy xem Last_IO_Error hoặc Last_SQL_Error từ đầu ra trạng thái nô lệ. Ví dụ:nếu bạn gặp lỗi sau:
Last_IO_Error: error connecting to master '[email protected]:3306' - retry-time: 60 retries: 2
Sau đó, chúng ta phải tạo người dùng sao chép trên bản chính đang hoạt động hiện tại, B:
mysql> CREATE USER [email protected] IDENTIFIED BY 'p4ss';
mysql> GRANT REPLICATION SLAVE ON *.* TO [email protected];
Sau đó, khởi động lại nô lệ trên A để bắt đầu sao chép lại:
mysql> STOP SLAVE;
mysql> START SLAVE;
Một lỗi phổ biến khác mà bạn sẽ thấy là dòng này:
Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: ...
Điều đó có thể có nghĩa là máy chủ đang gặp sự cố khi đọc tệp nhật ký nhị phân từ máy chủ hiện tại. Trong một số trường hợp, nô lệ có thể bị chậm lại do đó các sự kiện nhị phân cần thiết để bắt đầu sao chép đã bị thiếu trong bản chính hiện tại hoặc bản nhị phân trên bản chính đã bị xóa trong quá trình chuyển đổi dự phòng, v.v. Trong trường hợp này, cách tốt nhất là thực hiện đồng bộ hóa đầy đủ bằng cách sao lưu toàn bộ trên B và khôi phục lại trên A. Trên B, bạn có thể sử dụng mysqldump hoặc Percona Xtrabackup để sao lưu toàn bộ:
$ mysqldump -uroot -p --all-databases --single-transaction --triggers --routines > dump.sql # for mysqldump
$ xtrabackup --defaults-file=/etc/my.cnf --backup --parallel 1 --stream=xbstream --no-timestamp | gzip -6 - > backup-full-2019-04-16_071649.xbstream.gz # for xtrabackup
Chuyển tệp sao lưu sang A, khởi động lại cài đặt MySQL hiện có để dọn dẹp thích hợp và thực hiện khôi phục cơ sở dữ liệu:
$ systemctl stop mysqld # if mysql is still running
$ rm -Rf /var/lib/mysql # wipe out old data
$ mysqld --initialize --user=mysql # initialize database
$ systemctl start mysqld # start mysql
$ grep -i 'temporary password' /var/log/mysql/mysqld.log # retrieve the temporary root password
$ mysql -uroot -p -e 'ALTER USER [email protected] IDENTIFIED BY "p455word"' # mandatory root password update
$ mysql -uroot -p < dump.sql # restore the backup using the new root password
Sau khi được khôi phục, hãy thiết lập liên kết sao chép tới bản chính đang hoạt động B (192.168.0.42) và bật chế độ chỉ đọc. Trên A, hãy chạy các câu lệnh sau:
mysql> SET GLOBAL read_only = 1; /* enable read-only */
mysql> CHANGE MASTER TO MASTER_HOST = '192.168.0.42', MASTER_USER = 'rpl_user', MASTER_PASSWORD = 'p4ss', MASTER_AUTO_POSITION = 1; /* master information to connect */
mysql> START SLAVE; /* start replication */
mysql> SHOW SLAVE STATUS\G /* check replication status */
Đối với Percona Xtrabackup, vui lòng tham khảo trang tài liệu về cách khôi phục về A. Nó bao gồm bước điều kiện tiên quyết là chuẩn bị sao lưu trước khi thay thế thư mục dữ liệu MySQL.
Khi A đã bắt đầu sao chép chính xác, hãy theo dõi Seconds_Behind_Master ở trạng thái nô lệ. Điều này sẽ cung cấp cho bạn ý tưởng về việc nô lệ đã bỏ lại phía sau bao xa và bạn cần đợi bao lâu trước khi nó bắt kịp. Tại thời điểm này, kiến trúc của chúng tôi trông giống như sau:
Khi Seconds_Behind_Master giảm về 0, đó là thời điểm A đã bắt kịp với tư cách là một nô lệ cập nhật.
Nếu bạn đang sử dụng ClusterControl, bạn có tùy chọn để đồng bộ hóa nút bằng cách khôi phục từ bản sao lưu hiện có hoặc tạo và phát trực tiếp bản sao lưu từ nút chính đang hoạt động:
Sắp xếp máy chủ nô lệ với bản sao lưu hiện có là cách được khuyến nghị nên làm để xây dựng máy chủ phụ, vì nó không mang lại bất kỳ tác động nào đến máy chủ chính đang hoạt động khi chuẩn bị nút.
Thăng cấp Lão sư
Trước khi thăng cấp A làm chính mới, cách an toàn nhất là dừng tất cả hoạt động ghi trên B. Nếu không thể, chỉ cần buộc B hoạt động ở chế độ chỉ đọc:
mysql> SET GLOBAL read_only = 'ON';
mysql> SET GLOBAL super_read_only = 'ON';
Sau đó, trên A, chạy SHOW SLAVE STATUS và kiểm tra trạng thái sao chép sau:
Read_Master_Log_Pos: 45889974
Exec_Master_Log_Pos: 45889974
Seconds_Behind_Master: 0
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Giá trị của Read_Master_Log_Pos và Exec_Master_Log_Pos phải giống hệt nhau, trong khi Seconds_Behind_Master là 0 và trạng thái phải là 'Slave đã đọc tất cả nhật ký chuyển tiếp'. Đảm bảo rằng tất cả các nô lệ đã xử lý bất kỳ câu lệnh nào trong nhật ký chuyển tiếp của họ, nếu không bạn sẽ gặp rủi ro rằng các truy vấn mới sẽ ảnh hưởng đến các giao dịch từ nhật ký chuyển tiếp, gây ra tất cả các loại vấn đề (ví dụ:một ứng dụng có thể xóa một số hàng được truy cập bởi các giao dịch từ nhật ký chuyển tiếp).
Trên A, dừng sao chép và sử dụng câu lệnh RESET SLAVE ALL để xóa tất cả cấu hình liên quan đến sao chép và tắt chỉ đọc:
mysql> STOP SLAVE;
mysql> RESET SLAVE ALL;
mysql> SET GLOBAL read_only = 'OFF';
mysql> SET GLOBAL super_read_only = 'OFF';
Tại thời điểm này, A đã sẵn sàng chấp nhận ghi (read_only =OFF), tuy nhiên các nô lệ không được kết nối với nó, như minh họa bên dưới:
Đối với người dùng ClusterControl, việc quảng bá A có thể được thực hiện bằng cách sử dụng tính năng "Thúc đẩy Nô lệ" trong Hành động nút. ClusterControl sẽ tự động hạ cấp bậc chính đang hoạt động B, thăng cấp nô lệ A làm chủ và chỉ định lại C và D để sao chép từ A. B sẽ bị gạt sang một bên và người dùng phải chọn rõ ràng "Thay đổi bản sao chính" để tham gia lại B sao chép từ A ở giai đoạn sau .
Bổ nhiệm nô lệ
Bây giờ có thể an toàn để thay đổi chủ trên các nô lệ liên quan để sao chép từ A (192.168.0.41). Trên tất cả các nô lệ ngoại trừ E, hãy định cấu hình như sau:
mysql> STOP SLAVE;
mysql> CHANGE MASTER TO MASTER_HOST = '192.168.0.41', MASTER_USER = 'rpl_user', MASTER_PASSWORD = 'p4ss', MASTER_AUTO_POSITION = 1;
mysql> START SLAVE;
Nếu bạn là người dùng ClusterControl, bạn có thể bỏ qua bước này vì việc đặt hẹn lại được thực hiện tự động khi bạn quyết định thăng chức A trước đó.
Sau đó, chúng tôi có thể bắt đầu ứng dụng của mình để viết trên A. Tại thời điểm này, kiến trúc của chúng tôi trông giống như sau:
Từ chế độ xem cấu trúc liên kết ClusterControl, chúng tôi đã khôi phục cụm sao chép của mình về kiến trúc ban đầu trông giống như sau:
Lưu ý rằng thực hiện dự phòng ít rủi ro hơn nhiều nếu so với chuyển đổi dự phòng. Điều quan trọng là phải lên lịch thực hiện bài tập này vào giờ thấp điểm để giảm thiểu tác động đến doanh nghiệp của bạn.
Lời kết
Chuyển đổi dự phòng và hoạt động dự phòng phải được thực hiện cẩn thận. Hoạt động này khá đơn giản nếu bạn có một số lượng nhỏ các nút nhưng đối với nhiều nút với chuỗi sao chép phức tạp, nó có thể là một bài tập rủi ro và dễ xảy ra lỗi. Chúng tôi cũng đã chỉ ra cách ClusterControl có thể được sử dụng để đơn giản hóa các hoạt động phức tạp bằng cách thực hiện chúng thông qua giao diện người dùng, cộng với chế độ xem cấu trúc liên kết được hiển thị trong thời gian thực để bạn hiểu về cấu trúc liên kết sao chép mà bạn muốn xây dựng.