---
# System prepended metadata

title: Data Replicate
tags: [Documentation, Templates]

---

---
title: 'Data Replicate'
disqus: hackmd
---

Data Replication
===

## Table of Contents

[TOC]

## 1. Problems
Trước khi có database replication, các hệ thống cơ sở dữ liệu thường gặp phải những vấn đề sau:
### 1.1. **Khả năng chịu lỗi (Fault Tolerance)**
- **Vấn đề**: Nếu cơ sở dữ liệu chính (master) gặp sự cố hoặc hỏng hóc, toàn bộ hệ thống có thể bị gián đoạn hoặc ngừng hoạt động. Dữ liệu có thể bị mất hoặc không thể truy cập được cho đến khi hệ thống được khôi phục.
- **Replication**: Replication tạo ra các bản sao của dữ liệu trên nhiều node, giúp hệ thống có thể tiếp tục hoạt động ngay cả khi một phần của hệ thống gặp sự cố.
### 1.2. **Khả năng mở rộng (Scalability)**
- **Vấn đề**: Khi một hệ thống cơ sở dữ liệu chính phải xử lý một số lượng lớn các truy vấn đọc và ghi, nó có thể trở nên bị quá tải, dẫn đến giảm hiệu suất và khả năng đáp ứng.
- **Replication**: Với replication, các truy vấn đọc có thể được phân phối đến các slave, giảm tải cho master và cải thiện hiệu suất tổng thể của hệ thống.
### 1.3. **Sao lưu và phục hồi (Backup and Recovery)**
- **Vấn đề**: Quá trình sao lưu dữ liệu trực tiếp trên master có thể làm giảm hiệu suất của hệ thống và gây gián đoạn hoạt động bình thường.
- **Replication**: Sao lưu có thể được thực hiện trên các slave, giảm ảnh hưởng đến hoạt động của master và giúp hệ thống tiếp tục hoạt động trong khi sao lưu được thực hiện.
### 1.4. **Quản lý tải (Load Management)**
- **Vấn đề**: Nếu tất cả các truy vấn đọc và ghi đều được xử lý bởi master, nó có thể trở thành điểm nghẽn và dẫn đến hiệu suất không tốt.
- **Replication**: Replication cho phép phân phối các truy vấn đọc đến các slave, giúp cân bằng tải và cải thiện hiệu suất hệ thống.
### 1.5. **Khả năng phân phối (Distribution)**
- **Vấn đề**: Các hệ thống phân tán thường cần dữ liệu ở nhiều vị trí khác nhau để giảm độ trễ mạng và cải thiện khả năng truy cập dữ liệu.
- **Replication**: Replication cho phép các bản sao dữ liệu được đặt ở nhiều vị trí địa lý khác nhau, giúp cải thiện thời gian phản hồi và khả năng truy cập dữ liệu từ xa.
### 1.6. **Quản lý lỗi và khôi phục (Error Management and Recovery)**
- **Vấn đề**: Nếu có lỗi trong dữ liệu hoặc hệ thống, việc khôi phục có thể mất thời gian và phức tạp, làm gián đoạn dịch vụ.
- **Replication**: Có thể nhanh chóng khôi phục từ các bản sao chính xác của dữ liệu mà không cần khôi phục từ bản sao lưu.
### 1.7. **Bảo trì và nâng cấp (Maintenance and Upgrades)**
- **Vấn đề**: Thực hiện bảo trì hoặc nâng cấp hệ thống có thể gây gián đoạn dịch vụ hoặc giảm hiệu suất.
- **Replication**: Việc bảo trì có thể được thực hiện trên các slave trong khi master và các slave khác vẫn hoạt động bình thường.

## 2. Overview

- Data replication là quá trình sao chép và duy trì dữ liệu ở nhiều vị trí khác nhau. 
- Data Replication đảm bảo **tính sẵn sàng**, **độ tin cậy** và **hiệu suất** của dữ liệu.



Mô tả thực tế ý tưởng
---
### 2.1. Simple database
- Database truyền thống:
    ![image](https://hackmd.io/_uploads/B1GnTcmK0.png)
- Đối với những hệ thống nhỏ và vừa, Application có thể thao tác cả read và write lên master database

### 2.2. Master/Slave Model
- Tuy nhiên, khi hệ thống trở nên quá lớn và cần nâng cấp, ta cần thêm 1 node vào mô hình ở trên như sau: ![image](https://hackmd.io/_uploads/BJqKKiSK0.png)
- Master database chịu trách nhiệm chỉ ghi vào db và sau đó các Slave database clone từ Master database đó

- Ưu điểm: 
    - Dữ liệu được bảo toàn trong trường hợp Master DB gặp sự cố
    - Tăng hiệu suất của hệ thống
- Nhược điểm:
    - Triển khai phức tạp
    - Độ trễ giữa master và slave (Latency)

### 2.3. Mô tả chi tiết quá trình đồng bộ giữa Master và Slave
- Hình ảnh minh họa: ![image](https://hackmd.io/_uploads/Sy0uDGIKR.png)
- Slave và Master là 2 server chứa database
- Khi 1 Slave kết nối tới Master để bắt đầu quá trình đồng bộ, master sẽ tạo ra một **binlog dump** thread dành riêng cho kết nối đó.
- Khi có một thay đổi dữ liệu (DML commands: INSERT, UPDATE, DELETE) trên master server, những thay đổi này được ghi vào binary log.
- Lúc này, binlog dump thread sẽ đọc nội dung từ binary log và gửi cho Relay log trên Slave thông qua I/O thread
- Một SQL thread trên slave đọc nội dung từ relay log và áp dụng các thay đổi này vào database trên slave.


### 2.4. Latency Problem
- Tuy nhiên, mô hình Master/Slave gặp vấn đề về độ trễ.
- Nghĩa là khi application yêu cầu ghi, master database sẽ xử lý và trả về kết quả thành công
- Nhưng khi application yêu cầu đọc lại thông tin đã ghi trước đó, slave database chịu trách nhiệm đọc vẫn chưa cập nhật cho giống với master thì trả về giá trị cũ.
- Minh họa: ![image](https://hackmd.io/_uploads/S1669jHKA.png)
- Tèo là 1 người dùng cụ thể, anh ta đang muốn cập nhật avatar của mình và request yêu cầu ghi lên server. Khi server thấy yêu cầu ghi thì sẽ ghi vào trong master database và trả về trạng thái OK sau khi đã ghi thành công.
- Tuy nhiên, khi Tèo query lại cái avatar mà mình đã đổi thì lúc này server nhận thấy request đọc nên điều hướng đọc ở trong slave database. Mà lúc này giả sử slave database vẫn chưa đồng bộ với master thì nó sẽ trả về avatar cũ cho Tèo.



## 3. Triển khai Replication trên MySQL với Docker (Thủ công)

### 3.1. **Setup Docker Compose**

- Tạo file Docker Compose có tên là docker-compose.yml có nội dung như dưới đây để xác định các Master DB và Slave DB của MySQL:
- Code

```sql

version: "3"

services:
  mysql-master:
    image: mysql:8.0
    container_name: mysql-master
    command: --server-id=1 --log-bin=mysql-bin --binlog-format=row
    environment:
      MYSQL_ROOT_PASSWORD: Admin123
      MYSQL_DATABASE: mydatabase
      MYSQL_USER: replication_user
      MYSQL_PASSWORD: Admin123
      - "3307:3306"

  mysql-slave:
    image: mysql:8.0
    container_name: mysql-slave
    depends_on:
      - mysql-master
    command: --server-id=2 --log-bin=mysql-bin --binlog-format=row
    environment:
      MYSQL_ROOT_PASSWORD: Admin123
      MYSQL_DATABASE: mydatabase
      MYSQL_USER: replication_user
      MYSQL_PASSWORD: Admin123
    ports:
      - "3308:3306"
```

- Lưu ý: Nếu sử dụng mysql: lastest thì có khả năng gặp lỗi syntax khi chạy các bước sau nên trong document này xác định cụ thể phiên bản 8.0 của MySQL
- Cấu hình này thiết lập hai dịch vụ: mysql-master và mysql-slave

### 3.2. Khởi động container

- Chạy câu lệnh sau để tạo ở detached mode:
    
    ```sql
    docker-compose up -d
    ```
    
- Sau khi tạo thành công:

![image](https://hackmd.io/_uploads/SkAV5cBpR.png)


### 3.3. Cấu hình Master Server

- Chạy lần lượt các câu lệnh sau:
    
    ```powershell
    docker exec -it mysql-master bash
    mysql -uroot -p
    ```
    
- Mật khẩu là mật khẩu mình đặt ở trong file docker-compose.yml. Ở đây đặt là Admin123
- Cấu hình bằng các câu lệnh SQL sau:
    
    ```powershell
    ALTER USER 'replication_user'@'%' IDENTIFIED WITH 'mysql_native_password' BY 'replication_password';
    GRANT REPLICATION SLAVE ON *.* TO 'replication_user'@'%';
    FLUSH PRIVILEGES;
    SHOW MASTER STATUS;
    ```
    
- Chú ý ghi lại log file và position để cấu hình Replica Server ở phần tiếp theo

### 3.4. Cấu hình Replica Server (Slave Server)

- Sau khi thoát khỏi bash của Master Server, chạy 2 câu lệnh sau để bắt đầu cấu hình Slave Server:
    
    ```powershell
    docker exec -it mysql-slave bash
    mysql -uroot -p
    ```
    
- Mật khẩu là mật khẩu mình đặt ở trong file docker-compose.yml. Ở đây nên đặt là admin123
- Cấu hình bằng các câu lệnh SQL sau:
    
    ```powershell
    CHANGE MASTER TO
      MASTER_HOST='mysql-master',
      MASTER_USER='replication_user',
      MASTER_PASSWORD='replication_password',
      MASTER_LOG_FILE='mysql-bin.xxxxxx',
      MASTER_LOG_POS=xxxx;
    ```
    
- Thay thế các số x bằng số của log file và position đã ghi lại ở cuối phần 3

### 3.5. Start Replica Server và kiểm tra trạng thái

- Khởi động Slave Server:
    
    ```powershell
    START SLAVE;
    SHOW SLAVE STATUS\G
    ```
    
- Kiểm tra ở 2 server:
    - Ở Master Server:
        
        ```powershell
           use mydatabase;
           create table user (id int);
           insert into user values (1);
           select * from user;
        ```
        
    - Ở Slave Server:
        
        ```powershell
           use mydatabase;
           select * from user;
        ```