Rủi ro khi failover mysql replication
Mysql
44
failover
1
White

manhdung viết ngày 27/05/2015

Sơ lược về mysql replication:

Mysql replication là một kỹ thuật scale out database bằng cách sử dụng thêm nhiều database. Trong mô hình này, một database server đóng vai trò master. Writeset từ client được đẩy thẳng vào master. Master ghi lại các writeset này vào một file gọi là binlog. Nội dung binlog gần giống file dump, cũng bao gồm các statement SQL. Các database còn lại đóng vai trò slave sẽ sử dụng một IO_thread đọc binlog này qua network rồi ghi vào relay log. Tiếp đó, cũng trên slave, một SQL_thread sẽ thực hiện apply các writeset trong relay log này.

Ưu điểm

  • Scale out read cho hệ thống. Client có thể đọc data từ bất cứ node nào

  • Đơn giản

Nhược điểm:

  • Không thể scale out write. Client chỉ có thể ghi data vào một node đóng vai trò master. Trong quá trình tìm hiểu, tôi cũng tìm thấy có cách để thực hiện multi master cho mysql replication nhưng đó chỉ là một trick. Sử dụng cách làm đó trên production thì rất nguy hiểm vì bản thân mysql replication không có cơ chế giải quyết các conflict writeset mà một mô hình multi master cần có.

  • Việc failover hầu như phải thực hiện bằng tay. Trong các phiên bản mới hơn (từ 5.6), mysql đã cung cấp tính năng GTID và một số tool để hỗ trợ failover tự động như mysqlfailover nhưng cá nhân tôi trong quá trình sử dụng thử mysql GTID thấy có nhiều lỗi khó xử lý.

Tôi thực hiện failover như thế nào

Một mô hình gồm ba node: Một master và hai slave: slave1, slave2. Master thình lình bị down. Tôi vào hai slave1 và 2. Tôi thấy cả hai slave đã mất kết nối replication đến master:

Last_IO_Errno: 2003
Last_IO_Error: error reconnecting to master 'repl@192.168.3.252:3306' - retry-time: 60  retries: 1

Tôi bèn tắt IO_thread trên cả hai slave

stop slave io_thread;

Đợi cho đến khi cả hai slave đều xuất hiện dòng sau:

      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it

Dòng này cho biết slave đã thực hiện tất cả statement trong relay log.

Xem Master_Log _File, Read_Master_Log_Pos và Exec_Master_Log_Pos (Khi có dòng Slave has read all relay log; waiting for the slave I/O thread to update it thì hai giá trị Read_Master_Log_Pos và Exec_Master_Log_Pos phải bằng nhau ) trên từng slave. Nếu các giá trị giống nhau thì khi đó chắc chắn data của hai slave đồng bộ. Nếu slave1, slave2 có cấu hình phần cứng giống nhau thì tôi có thể chọn một trong hai slave bất kỳ để đưa lên làm master. Giả sử tôi chọn slave1.

Trên slave1, tôi thực hiện

stop slave;
reset slave all;

để làm slave1 quên đi old master.

Sau đó, tôi thực hiện:

reset master;

để reset binlog của slave1. Nếu slave1 có tạo binlog (nếu như tôi cấu hình log_slave_updates=1) thì lệnh trên sẽ xóa toàn bộ binlog và khởi tạo lại binlog từ mysql-bin.000001 và log pos là 120. Đây chỉ là để làm gọn, tôi có thể không làm bước này.

Trên slave2, tôi thực hiện

stop slave;
reset slave all;

để làm slave1 quên đi old master.

Sau đó, tôi thực hiện change master to... đến slave1.

Rủi ro khi failover

Khi tìm hiểu quá trình failover sâu hơn thì tôi thấy thời điểm mà master bị down, hệ thống cần failover thì rất dễ xảy ra mất đồng bộ dữ liệu trên các node.

Vấn đề nằm trong quy trình failover ở trên là:

Điêu kiện để quy trình hoàn thành là slave1, slave2 cùng đạt đến một điểm: cùng Master_Log_File và cùng Read_Master_Log_Pos. Vì một lý do nào đó ngay trước khi master down, slave2 bị lag replication thì khi đó giá trị Read_Master_Log_Pos của hai slave sẽ không giống nhau. Sau khi thực hiện xong toàn bộ statement trong relay log, slave1 và slave2 sẽ có tập data không đồng nhất. Giả sử slave2 lag nên dataset của slave1 sẽ lớn hơn dataset của slave2: slave1, slave2 cùng master log file nhưng master log pos của slave1 là 1000, của slave2 là 500 . Lúc này, nếu tôi failover đến slave1 thì slave2 sẽ mất một phần data trong khoảng pos 500 đến 100. Còn ngược lại nếu failover đến slave2 thì slave1 sẽ cứ nhiều data hơn slave2. Rủi thay, nếu sau này client cần query dữ liệu mà lại nằm trong đoạn sai biệt đó thì slave1 sẽ không thể phục vụ được hoặc những cập nhật lên dữ liệu nằm trong vùng sai biệt đó (slave2 không có) có thể làm break replication của slave2.

Nếu hệ replication chỉ có một master, một slave thì tôi không thể gặp rủi ro trên.

Giải pháp có thể là gì

  • Giải pháp 1:

Không thực hiện reset master để bảo toàn binlog. Thực hiện so sánh last pos của slave1 và slave2 để tìm ra các log pos mà slave 1 có nhưng slave 2 không có. Sử dụng mysqlbinlog trên slave1 để cắt ra các đoạn log pos này thành một script sql. Cuối cùng đem script này import lên slave2. Sau khi data hai slave đồng nhất mới tiến hành change master to

  • Giải pháp 2:

Chọn slave có nhiều data làm master. Tiến hành change master to như bình thường. Có thể reset master nếu muốn. Sau khi hệ replication mới đã hình thành, tôi chạy hai tool có tên là pt-table-cheksum và pt-table-sync trong bộ percona toolkit để xác định sự sai biệt dataset và đồng bộ data lại. Cách này dù vậy có vài hạn chế nằm ở chính hai tool trên. Hai tool này hoạt động không chính xác lắm nếu slave1 và 2 là hai biến thể mysql khác nhau hoặc cùng biến thể nhưng khác phiên bản.

Thực ra, tôi may mắn chưa từng gặp rủi ro như trên. Bài viết này được viết trong một ngữ cảnh giả định. Vì chưa qua kiểm chứng thực tế nên nếu bạn nào thấy có lỗ hổng xin để lại comment góp ý cho tôi

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

manhdung

44 bài viết.
263 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
76 11
Giới thiệu RabbitMQ là một message broker ( messageoriented middleware) sử dụng giao thức AMQP Advanced Message Queue Protocol (Đây là giao thức ph...
manhdung viết 3 năm trước
76 11
White
48 4
Giả định bạn tiếp nhận một server mới toanh, bạn cần tìm một số thông tin về nó như loại CPU, loại main, loại memory, memory dùng của hãng nào... c...
manhdung viết gần 2 năm trước
48 4
White
41 12
Trong phần 1, tôi đã giới thiệu về sơ lược rabbitmq, vai trò của rabbitmq trong hệ thống phân tán và hướng dẫn cài đặt. Trong phần này, tôi sẽ trìn...
manhdung viết 3 năm trước
41 12
Bài viết liên quan
White
20 0
Mysql innodb internal là một chủ đề khá sâu. Bản thân tôi cũng chưa bao quát hết. Bài viết này chỉ cung cấp một cái nhìn sơ lược. Để các bạn khôn...
manhdung viết 3 năm trước
20 0
White
25 2
(Ảnh) Tiêu đề chỉ là câu khách :v, thực ra là có một vài điểm về mysql explain mà chắc chưa nhiều bạn biết, tớ cũng hay quên nên note lại cho nhớ ...
LinhPT viết gần 3 năm trước
25 2
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
44 bài viết.
263 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!