1 Thiết lập sao chép MySQL
# Khi chỉ có một máy chủ CSDL
-Tất cả các thao tác đọc/ghi đều tập trung trên một máy chủ MySQL
-Số lượng kết nối tăng cao gây quá tải
-Giải pháp: Tách thành hai máy chủ - một máy chủ chuyên ghi (master) và một máy chuyên đọc (slave)
-Yêu cầu: Đồng bộ dữ liệu giữa hai máy chủ theo thời gian thực
-Lợi ích:
* Giảm áp lực truy vấn đọc bằng cách phân tán sang nhiều slave
* Hỗ trợ cấu hình 1 master - 1 slave hoặc 1 master - nhiều slave
# Nguyên lý hoạt động sao chép:
1) Master ghi lại các thay đổi vào file nhật ký nhị phân (binlog)
2) Slave sử dụng thread I/O để tải về binlog từ master
3) Thread I/O thứ hai ghi binlog vào file relay log trên slave
4) Thread SQL thực thi các thao tác từ relay log lên cơ sở dữ liệu slave
1.1 Quy trình triển khai
# 1 Chuẩn bị hai máy chủ (sử dụng Docker container mô phỏng)
-docker pull mysql:5.7
# 2 Tạo cấu trúc thư mục cho hai instance
mkdir -p /opt/mysql/master/{conf.d,data}
touch /opt/mysql/master/my.cnf
mkdir -p /opt/mysql/slave/{conf.d,data}
touch /opt/mysql/slave/my.cnf
# 3 Cấu hình master
[mysqld]
user=mysql
character-set-server=utf8mb4
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO
max_connections=1000
server-id=200
log-bin=mysql-bin
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
# 4 Cấu hình slave
[mysqld]
user=mysql
character-set-server=utf8mb4
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO
max_connections=1000
server-id=201
log-bin=mysql-slave-bin
relay_log=slave-relay-bin
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
# 5 Khởi động các container
docker run -d -v /opt/mysql/master/data:/var/lib/mysql \
-v /opt/mysql/master/conf.d:/etc/mysql/conf.d \
-v /opt/mysql/master/my.cnf:/etc/mysql/my.cnf \
-p 33307:3306 --name mysql-master \
-e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
docker run -d -v /opt/mysql/slave/data:/var/lib/mysql \
-v /opt/mysql/slave/conf.d:/etc/mysql/conf.d \
-v /opt/mysql/slave/my.cnf:/etc/mysql/my.cnf \
-p 33306:3306 --name mysql-slave \
-e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
# 6 Cấu hình tài khoản truy cập master
mysql -h 10.0.0.200 -P 33307 -uroot -p
CREATE USER 'replicator'@'%' IDENTIFIED BY 'repl_pass';
GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'%';
FLUSH PRIVILEGES;
SHOW MASTER STATUS;
# 7 Cấu hình slave
mysql -h 10.0.0.200 -P 33306 -uroot -p
CHANGE MASTER TO
MASTER_HOST='10.0.0.200',
MASTER_PORT=33307,
MASTER_USER='replicator',
MASTER_PASSWORD='repl_pass',
MASTER_LOG_FILE='mysql-bin.000003',
MASTER_LOG_POS=154;
START SLAVE;
SHOW SLAVE STATUS\G;
2 Triển khai phân tách đọc ghi trong Django
# 1 Cấu hình DATABASES
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'main_db.sqlite3',
},
'replica': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'replica_db.sqlite3',
}
}
# 2 Tạo model
class Product(models.Model):
title = models.CharField(max_length=64)
price = models.DecimalField(max_digits=10, decimal_places=2)
# 3 Di chuyển dữ liệu
python manage.py makemigrations
python manage.py migrate --database=replica
# 4 Triển khai logic
# Cách 1: Chỉ định trực tiếp
Product.objects.using('replica').filter(...)
# Cách 2: Tự động phân tách
# Tạo file db_router.py
class ReadWriteRouter:
def db_for_read(self, model, **hints):
return 'replica'
def db_for_write(self, model, **hints):
return 'default'
# Cấu hình trong settings.py
DATABASE_ROUTERS = ['myproject.db_router.ReadWriteRouter']
3 Môi trường phát triển trên Linux từ Windows
# Giải pháp phát triển trên Windows nhưng chạy trên Linux
# Cấu hình PyCharm sử dụng interpreter từ máy chủ Linux
# Lợi ích:
- Kiểm tra tương thích với môi trường sản phẩm
- Tránh các lỗi do khác biệt hệ điều hành
4 Kết nối Docker từ xa
4.1 Hướng dẫn cài đặt
# Cấu hình Docker để cho phép kết nối từ xa
# 1 Sửa file cấu hình Docker
sudo vim /etc/docker/daemon.json
{
"hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"]
}
# 2 Khởi động lại Docker
sudo systemctl restart docker
# 3 Kiểm tra kết nối
curl --unix-socket /var/run/docker.sock http://localhost/version