Saturday, January 18, 2025

Replication Master-Slave Database MySQL

-

1. Tổng quan.

Đây là một hướng dẫn cấu hình cơ bản cho hệ thống Replication Database MySQL (hoặc MariaDB) theo mô hình Replication Master-Slave.

Trong mô hình này, một database được cấu hình là Master và một hoặc nhiều databases khác được cấu hình là Slave. Mọi thay đổi (INSERT, UPDATE, DELETE, v.v.) trên Master sẽ được sao chép tự động đến các Slave.

Cấu hình này có thể được dùng để sao lưu, tăng hiệu suất đọc (vì Slave có thể xử lý các truy vấn chỉ đọc) hoặc thậm chí hỗ trợ trong việc triển khai các hệ thống với tính sẵn sàng cao.

Một số điểm cần lưu ý.

Hệ thống này sử dụng MariaDB và có thể tương thích với MySQL, với hệ thống này dữ liệu không được đồng bộ hai chiều giữa hai node. Đây là một dạng đồng bộ một chiều:

  • Node Master: Chỉ định thực hiện các thao tác ghi (INSERT, UPDATE, DELETE).
  • Node Slave: Chỉ thực hiện thao tác đọc và sao chép các thay đổi từ Master thông qua các binary log. Slave không gửi dữ liệu ngược lại cho Master.

Nếu bạn muốn đồng bộ hai chiều (Master-Master):

Bạn cần sử dụng Master-Master Replication, nơi cả hai node đều vừa là Master vừa là Slave. Trong mô hình Master-Master Replication, mọi thay đổi ở một node sẽ được đồng bộ ngược lại qua node kia.

Hoặc bạn có thể triển khai Galera Cluster, hỗ trợ đồng bộ dữ liệu giữa tất cả các node theo mô hình multi-master.

2. Mô hình Master-Slave Replication.

Master:

  • Khi có bất kỳ lệnh DML (Data Manipulation Language) nào được thực hiện (như INSERT, UPDATE, DELETE), những thay đổi này sẽ được ghi vào binary log của Master.
  • Một Binlog dump thread trên Master sẽ gửi nội dung của binary log cho Slave thông qua network.

Slave:

  • Slave có một I/O thread chịu trách nhiệm kết nối với Master và yêu cầu dữ liệu từ binary log.
  • Khi nhận được dữ liệu, Slave sẽ lưu trữ nội dung từ binary log của Master vào Relay log trên chính Slave.
  • Sau đó, một SQL thread trên Slave sẽ đọc Relay log và áp dụng các thay đổi vào database của Slave.

3. Quy trình triển khai.

Dưới đây là quy trình đầy đủ để thiết lập replication giữa Master (node 1: 10.237.7.71) và Slave (node 2: 10.237.7.72).

Bước 1: Cài đặt Chrony và thiết lập múi giờ.

Việc đồng bộ thời gian giữa các node là rất quan trọng. Chúng ta sẽ sử dụng Chrony để đảm bảo thời gian trên các node luôn đồng nhất.

Cài đặt múi giờ.

timedatectl set-timezone Asia/Ho_Chi_Minh

Cài đặt Chrony.

apt update
apt install chrony -y

Thay đổi nội dung file /etc/chrony/chrony.conf với nội dung dưới, 10.237.7.250 là NTP Server.

echo 'server 10.237.7.250 iburst' > /etc/chrony/chrony.conf

Khởi động và bật tính năng tự khởi động theo OS cho Chrony.

systemctl restart chrony
systemctl enable chrony

Check source NTP Server xem đúng chưa bằng lệnh chronyc sources.

shell> chronyc sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* 10.237.7.250                  3   7   377    10    -20us[  -27us] +/-   86ms

Lệnh chronyc tracking sẽ cho bạn xem trạng thái đồng bộ NTP, nếu tham số leap status là normal tức là thời gian đã được đồng bộ với NTP Server.

shell> chronyc tracking
Reference ID    : 0AED07FA (10.237.7.250)
Stratum         : 4
Ref time (UTC)  : Wed Oct 16 04:13:11 2024
System time     : 0.000003247 seconds slow of NTP time
Last offset     : -0.000007498 seconds
RMS offset      : 0.000019078 seconds
Frequency       : 1.251 ppm fast
Residual freq   : -0.002 ppm
Skew            : 0.061 ppm
Root delay      : 0.055179413 seconds
Root dispersion : 0.040634494 seconds
Update interval : 129.4 seconds
Leap status     : Normal

Bước 2: Cài đặt MariaDB trên cả hai node.

apt-get install software-properties-common -y
apt update
apt install mariadb-server mariadb-client mariadb-common -y

Xác minh MariaDB đã cài đặt thành công bằng lệnh mariadb --version, phiên bản mới nhất thời điểm hiện tại là 15.1.

shell> mysql --version
mysql  Ver 15.1 Distrib 10.2.21-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2

Bước 2: Cấu hình Master (Node 1: 10.237.7.71).

Chỉnh sửa cấu hình MariaDB trên node 1 (Master):

Mở file cấu hình /etc/mysql/mariadb.conf.d/50-server.cnf và đảm bảo các tham số sau:

cat > /etc/mysql/mariadb.conf.d/50-server.cnf << 'OEF'
[client]
port            = 3306
socket          = /var/run/mysqld/mysqld.sock
[mysqld_safe]
socket          = /var/run/mysqld/mysqld.sock
nice            = 0

[mysqld]
log-bin
server_id=1
replicate-do-db=keystone_sw_auth_2
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
lc_messages_dir = /usr/share/mysql
lc_messages     = en_US
skip-external-locking
bind-address            = 0.0.0.0
max_connections         = 1000
connect_timeout         = 5
wait_timeout            = 3600
max_allowed_packet      = 16M
thread_cache_size       = 128
sort_buffer_size        = 4M
bulk_insert_buffer_size = 16M
tmp_table_size          = 32M
max_heap_table_size     = 32M
skip-name-resolve       = 1
myisam_recover_options = BACKUP
key_buffer_size         = 128M
table_open_cache        = 400
myisam_sort_buffer_size = 512M
concurrent_insert       = 2
read_buffer_size        = 2M
read_rnd_buffer_size    = 1M
query_cache_limit               = 128K
query_cache_size                = 64M
log_warnings            = 2
slow_query_log_file     = /var/log/mysql/mariadb-slow.log
long_query_time = 10
log_slow_verbosity      = query_plan
log_bin                 = /var/log/mysql/mariadb-bin
log_bin_index           = /var/log/mysql/mariadb-bin.index
expire_logs_days        = 10
max_binlog_size         = 100M
default_storage_engine  = InnoDB
innodb_buffer_pool_size = 256M
innodb_log_buffer_size  = 8M
innodb_file_per_table   = 1
innodb_open_files       = 400
innodb_io_capacity      = 400
innodb_flush_method     = O_DIRECT

[galera]

[mysqldump]
quick
quote-names
max_allowed_packet      = 16M

[mysql]

[isamchk]
key_buffer              = 16M
OEF

File /etc/mysql/conf.d/50-server.cnf chứa các thiết lập cấu hình cho MySQL hoặc MariaDB, và trong trường hợp này, nó được sử dụng để cấu hình các tùy chọn cho quá trình khởi động của dịch vụ MySQL/MariaDB, cụ thể là cho mysqld_safe.

cat > /etc/mysql/conf.d/50-server.cnf << 'OEF'
[mysqld_safe]
skip_log_error
syslog
OEF
  • mysqld_safe: cung cấp một lớp bảo vệ bổ sung và giúp tự động khởi động lại MySQL trong trường hợp quá trình bị dừng đột ngột hoặc gặp lỗi:
    • skip_log_error: Tùy chọn này có thể hữu ích trong các trường hợp bạn không muốn ghi log lỗi vào một file riêng biệt mà chỉ cần ghi chung vào syslog, giảm bớt dung lượng lưu trữ cho file log riêng của MySQL.
    • syslog: Cấu hình này giúp đưa tất cả thông tin log của MySQL/MariaDB vào hệ thống quản lý log tập trung của hệ điều hành, dễ dàng hơn trong việc giám sát log trên toàn bộ hệ thống, thay vì phải truy cập log file riêng của MySQL.

Để bỏ qua bước hỏi mật khẩu khi sử dụng lệnh MySQL mà tài khoản root không có mật khẩu, bạn có thể thực hiện một trong những cách sau:

Dùng tùy chọn --password='' (không có mật khẩu).

Khi tài khoản root không có mật khẩu, bạn có thể thêm tùy chọn --password='' để bỏ qua yêu cầu nhập mật khẩu. Ví dụ:

mysql -u root --password='' -e "USE keystone_sw_auth_2; INSERT INTO test_table VALUES (1, 'Hello World 4');"

Trong trường hợp này, không cần phải nhập mật khẩu khi được hỏi.

Sử dụng file cấu hình /etc/mysql/debian.cnf.

Nếu bạn không muốn phải nhập mật khẩu (hoặc tránh việc thêm tùy chọn --password='' mỗi lần chạy lệnh), bạn có thể thiết lập thông tin đăng nhập mặc định trong file /etc/mysql/debian.cnf.

cat > /etc/mysql/debian.cnf << 'OEF'
[client]
host     = localhost
user     = root
password = ""

[mysql_upgrade]
host     = localhost
user     = root
password = ""
OEF

Sau khi tạo xong file, bạn có thể chạy lệnh mà không cần chỉ định mật khẩu:

mysql -e "USE keystone_sw_auth_2; INSERT INTO test_table VALUES (1, 'Hello World 4');"

Khởi động lại MariaDB để áp dụng các thay đổi:

systemctl restart mariadb

Tạo database keystone_sw_auth_2.

mysql -e "CREATE DATABASE keystone_sw_auth_2;"

Mở MySQL trên node Master (10.237.7.71) và tạo user cho việc replication:

mysql -e "CREATE USER 'replicator'@'10.237.7.72' IDENTIFIED BY 'password';"
mysql -e "GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'10.237.7.72';"
mysql -e "FLUSH PRIVILEGES;"

Khóa các bảng để sao lưu dữ liệu hiện tại:

mysql -e "FLUSH TABLES WITH READ LOCK;"

Xác định vị trí của log bin bằng cách kiểm tra trạng thái của replication trên node Master:

shell> mysql -e "SHOW MASTER STATUS;"
+--------------------+----------+--------------+------------------+
| File               | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+--------------------+----------+--------------+------------------+
| mariadb-bin.000001 |      957 |              |                  |
+--------------------+----------+--------------+------------------+

Lưu ý giá trị của File và Position (ví dụ: mariadb-bin.000001Position=957).

Sao lưu dữ liệu hiện tại của database.

Bạn có thể sử dụng mysqldump để sao lưu dữ liệu và chuyển sang node Slave:

mysqldump --databases keystone_sw_auth_2 > /tmp/dbdump.sql
scp /tmp/dbdump.sql root@10.237.7.72:/tmp/dbdump.sql

Mở khóa các bảng: Sau khi sao lưu xong, mở khóa các bảng:

mysql -e "UNLOCK TABLES;"

Bước 4: Cấu hình Slave (Node 2: 10.237.7.72).

Chỉnh sửa cấu hình MariaDB trên node 2 (Slave): Mở file cấu hình /etc/mysql/mariadb.conf.d/50-server.cnf và thiết lập các thông số sau:

cat > /etc/mysql/mariadb.conf.d/50-server.cnf << 'OEF'
[client]
port            = 3306
socket          = /var/run/mysqld/mysqld.sock

[mysqld_safe]
socket          = /var/run/mysqld/mysqld.sock
nice            = 0

[mysqld]
log-bin
server_id=2
replicate-do-db=keystone_sw_auth_2
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
lc_messages_dir = /usr/share/mysql
lc_messages     = en_US
skip-external-locking
bind-address            = 0.0.0.0
max_connections         = 1000
connect_timeout         = 5
wait_timeout            = 3600
max_allowed_packet      = 16M
thread_cache_size       = 128
sort_buffer_size        = 4M
bulk_insert_buffer_size = 16M
tmp_table_size          = 32M
max_heap_table_size     = 32M
skip-name-resolve       = 1
myisam_recover_options = BACKUP
key_buffer_size         = 128M
table_open_cache        = 400
myisam_sort_buffer_size = 512M
concurrent_insert       = 2
read_buffer_size        = 2M
read_rnd_buffer_size    = 1M
query_cache_limit               = 128K
query_cache_size                = 64M
general_log_file        = /var/log/mysql/mysql.log
log_warnings            = 2
slow_query_log_file     = /var/log/mysql/mariadb-slow.log
long_query_time = 10
log_slow_verbosity      = query_plan
log_bin                 = /var/log/mysql/mariadb-bin
log_bin_index           = /var/log/mysql/mariadb-bin.index
expire_logs_days        = 10
max_binlog_size         = 100M
default_storage_engine  = InnoDB
innodb_buffer_pool_size = 256M
innodb_log_buffer_size  = 8M
innodb_file_per_table   = 1
innodb_open_files       = 400
innodb_io_capacity      = 400
innodb_flush_method     = O_DIRECT
[galera]

[mysqldump]
quick
quote-names
max_allowed_packet      = 16M

[mysql]

[isamchk]
key_buffer              = 16M
OEF

Giống như server master thì server slave mình cũng tạo file /etc/mysql/conf.d/50-server.cnf nhé.

cat > /etc/mysql/conf.d/50-server.cnf << 'OEF'
[mysqld_safe]
skip_log_error
syslog
OEF

Và file cấu hình /etc/mysql/debian.cnf.

cat > /etc/mysql/debian.cnf << 'OEF'
[client]
host     = localhost
user     = root
password = ""

[mysql_upgrade]
host     = localhost
user     = root
password = ""
OEF

Khởi động lại MariaDB để áp dụng các thay đổi:

systemctl restart mariadb

Import DB từ Master (từ file dbdump.sql đã sao lưu):

mysql < /tmp/dbdump.sql

Mở MySQL trên node Slave (10.237.7.72) và thiết lập thông tin replication:

mysql -e "CHANGE MASTER TO
MASTER_HOST='10.237.7.71',
MASTER_USER='replicator',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mariadb-bin.000001',
MASTER_LOG_POS=957;"

Xác minh lại kết quả.

shell> mysql -e "SHOW MASTER STATUS;"
+--------------------+----------+--------------+------------------+
| File               | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+--------------------+----------+--------------+------------------+
| mariadb-bin.000001 |     957  |              |                  |
+--------------------+----------+--------------+------------------+

Bắt đầu replication

mysql -e "START SLAVE";

Kiểm tra trạng thái của Slave để đảm bảo replication đang hoạt động:

shell> mysql -e "SHOW SLAVE STATUS\G;"
*************************** 1. row ***************************
                Slave_IO_State: Waiting for master to send event
                   Master_Host: 10.237.7.71
                   Master_User: replicator
                   Master_Port: 3306
                 Connect_Retry: 60
               Master_Log_File: mariadb-bin.000001
           Read_Master_Log_Pos: 957
                Relay_Log_File: mysqld-relay-bin.000002
                 Relay_Log_Pos: 557
         Relay_Master_Log_File: mariadb-bin.000001
              Slave_IO_Running: Yes
             Slave_SQL_Running: Yes
               Replicate_Do_DB: keystone_sw_auth_2
           Replicate_Ignore_DB:
            Replicate_Do_Table:
        Replicate_Ignore_Table:
       Replicate_Wild_Do_Table:
   Replicate_Wild_Ignore_Table:
                    Last_Errno: 0
                    Last_Error:
                  Skip_Counter: 0
           Exec_Master_Log_Pos: 957
               Relay_Log_Space: 867
               Until_Condition: None
                Until_Log_File:
                 Until_Log_Pos: 0
            Master_SSL_Allowed: No
            Master_SSL_CA_File:
            Master_SSL_CA_Path:
               Master_SSL_Cert:
             Master_SSL_Cipher:
                Master_SSL_Key:
         Seconds_Behind_Master: 0
 Master_SSL_Verify_Server_Cert: No
                 Last_IO_Errno: 0
                 Last_IO_Error:
                Last_SQL_Errno: 0
                Last_SQL_Error:
   Replicate_Ignore_Server_Ids:
              Master_Server_Id: 1
                Master_SSL_Crl:
            Master_SSL_Crlpath:
                    Using_Gtid: No
                   Gtid_IO_Pos:
       Replicate_Do_Domain_Ids:
   Replicate_Ignore_Domain_Ids:
                 Parallel_Mode: optimistic
                     SQL_Delay: 0
           SQL_Remaining_Delay: NULL
       Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
              Slave_DDL_Groups: 0
Slave_Non_Transactional_Groups: 0
    Slave_Transactional_Groups: 0

Nếu replication hoạt động bình thường, bạn sẽ thấy Slave_IO_Running: Yes và Slave_SQL_Running: Yes.

Bước 5: Kiểm tra.

Đầu tiên hãy tạo một table mới trên Master (node 1) ví dụ mình tạo test_table.

mysql -e "USE keystone_sw_auth_2; CREATE TABLE test_table (id INT, data VARCHAR(100));"

Thử insert dữ liệu vào Master (node 1) và kiểm tra xem dữ liệu có được replicate sang Slave (node 2) không.

mysql -e "USE keystone_sw_auth_2; INSERT INTO test_table VALUES (1, 'Hello World 1');"

Truy cập Slave và kiểm tra xem dữ liệu đã replicate:

shell> mysql -e "USE keystone_sw_auth_2; SELECT * FROM test_table;"
+------+---------------+
| id   | data          |
+------+---------------+
|    1 | Hello World 1 |
+------+---------------+

Thử insert dữ liệu vào Slave (node 2) và kiểm tra xem dữ liệu có được replicate sang Master (node 1) không.

mysql -e "USE keystone_sw_auth_2; INSERT INTO test_table VALUES (1, 'Hello World 2');"

Kết quả đã insert dữ liệu thành công trên Slave.

shell> mysql -e "USE keystone_sw_auth_2; SELECT * FROM test_table;"
+------+---------------+
| id   | data          |
+------+---------------+
|    1 | Hello World 1 |
|    1 | Hello World 2 |
+------+---------------

Truy cập Master và kiểm tra thì dữ liệu không được replicate, điều này là hợp lệ do mô hình Replication Master-Slave dữ liệu chỉ đồng bộ một chiều từ Master sang Slave.

shell> mysql -e "USE keystone_sw_auth_2; SELECT * FROM test_table;"
+------+---------------+
| id   | data          |
+------+---------------+
|    1 | Hello World 1 |
+------+---------------+

Bước 6: (Tùy chọn) Thiết lập giám sát và bảo trì.

  • Thiết lập công cụ giám sát replication để theo dõi quá trình.
  • Tự động hóa quy trình failover trong trường hợp Master gặp sự cố (sử dụng công cụ như MHA hoặc HAProxy).

Với quy trình này, bạn sẽ thiết lập thành công replication giữa hai node.

4. Một số cách để debug khi gặp lỗi.

Kiểm tra và đồng bộ hóa phiên bản MariaDB trên cả hai node.

Hãy chắc chắn rằng cả hai node đang chạy cùng một phiên bản MariaDB. Bạn có thể kiểm tra bằng lệnh:

mysql --version

Nếu phiên bản không khớp, bạn cần nâng cấp hoặc hạ cấp một trong hai node để phiên bản khớp với nhau.

Kiểm tra tính toàn vẹn của file binary log.

Có thể file binary log của master sẽ bị hỏng. Bạn có thể thử tạo một file binary log mới bằng cách chạy lệnh trên node master:

FLUSH LOGS;

Điều này sẽ tạo một file binary log mới và node slave sẽ đọc từ file mới này.

Đặt lại replication từ node slave.

Nếu vấn đề vẫn tồn tại, bạn có thể thử đặt lại replication trên node slave:

Trên node slave (10.237.7.72):

STOP SLAVE;
RESET SLAVE ALL;

Sau đó, thiết lập lại replication với thông tin mới từ node master:

CHANGE MASTER TO
MASTER_HOST='10.237.7.71',
MASTER_USER='replicator',
MASTER_PASSWORD='your_password',
MASTER_LOG_FILE='mariadb-bin.000001',
MASTER_LOG_POS=123;

Sau đó, khởi động lại replication:

START SLAVE;

Kiểm tra firewall và kết nối mạng.

Kiểm tra firewall giữa các node để đảm bảo rằng cổng 3306 mở cho kết nối từ slave đến master. Bạn có thể dùng lệnh sau để kiểm tra kết nối từ slave đến master:

telnet 10.237.7.71 3306

Nếu không thể kết nối, hãy kiểm tra firewall trên cả hai node và đảm bảo rằng cổng 3306 không bị chặn.

Kiểm tra quyền của tài khoản replicator.

Đảm bảo tài khoản replicator có đủ quyền thực hiện replication. Bạn có thể kiểm tra quyền của tài khoản trên node master:

SHOW GRANTS FOR 'replicator'@'10.237.7.72';

Nếu quyền không đủ, bạn có thể cấp lại quyền:

GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'10.237.7.72' IDENTIFIED BY 'your_password';
FLUSH PRIVILEGES;

Sau khi thực hiện các bước trên, kiểm tra lại trạng thái replication với:

SHOW SLAVE STATUS\G;
  • Nếu vẫn gặp vấn đề:
    • Kiểm tra log của MariaDB: Kiểm tra file log để có thêm chi tiết về lỗi, file log thường nằm tại /var/log/mysql/error.log.
    • Kiểm tra cấu hình replication: Đảm bảo cấu hình trong my.cnf là chính xác.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories